mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-21 10:09:57 +01:00
Merge branch 'STABLE-BRANCH-2-4'
-- Fixed conflicts: NEWS configure.ac doc/gpg.texi
This commit is contained in:
commit
dfa60c09f5
2
AUTHORS
2
AUTHORS
@ -16,7 +16,7 @@ List of Copyright holders
|
||||
=========================
|
||||
|
||||
Copyright (C) 1997-2019 Werner Koch
|
||||
Copyright (C) 2003-2023 g10 Code GmbH
|
||||
Copyright (C) 2003-2024 g10 Code GmbH
|
||||
Copyright (C) 1994-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
||||
Copyright (C) 1995-1997, 2000-2007 Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||
|
@ -191,7 +191,7 @@ endif
|
||||
|
||||
|
||||
gen_start_date = 2011-12-01T06:00:00
|
||||
.PHONY: gen-ChangeLog
|
||||
.PHONY: gen-ChangeLog stowinstall speedo
|
||||
gen-ChangeLog:
|
||||
if test -e $(top_srcdir)/.git; then \
|
||||
(cd $(top_srcdir) && \
|
||||
@ -207,6 +207,11 @@ gen-ChangeLog:
|
||||
stowinstall:
|
||||
$(MAKE) $(AM_MAKEFLAGS) install prefix=/usr/local/stow/gnupg
|
||||
|
||||
|
||||
speedo:
|
||||
$(MAKE) -f $(top_srcdir)/build-aux/speedo.mk native SELFCHECK=0
|
||||
|
||||
|
||||
TESTS_ENVIRONMENT = \
|
||||
LC_ALL=C \
|
||||
EXEEXT=$(EXEEXT) \
|
||||
|
107
NEWS
107
NEWS
@ -3,9 +3,104 @@ Noteworthy changes in version 2.5.0 (unreleased)
|
||||
|
||||
Changes also found in 2.4.4:
|
||||
|
||||
* gpgsm: Support ECDSA in de-vs compliance mode. [T6802]
|
||||
* gpg: Do not keep an unprotected smartcard backup key on disk. See
|
||||
https://gnupg.org/blog/20240125-smartcard-backup-key.html for a
|
||||
security advisory. [T6944]
|
||||
|
||||
* gpg: Allow to specify seconds since Epoch beyond 2038 on 32-bit
|
||||
platforms. [T6736]
|
||||
|
||||
* gpg: Fix expiration time when Creation-Date is specified. [T5252]
|
||||
|
||||
* gpg: Add support for Subkey-Expire-Date. [rG96b69c1866]
|
||||
|
||||
* gpg: Add option --with-v5-fingerprint. [T6705]
|
||||
|
||||
* gpg: Add sub-option ignore-attributes to --import-options.
|
||||
[rGd4976e35d2]
|
||||
|
||||
* gpg: Add --list-filter properties sig_expires/sig_expires_d.
|
||||
[rGbf662d0f93af]
|
||||
|
||||
* gpg: Fix validity of re-imported keys. [T6399]
|
||||
|
||||
* gpg: Report BEGIN_ status before examining the input. [T6481]
|
||||
|
||||
* gpg: Don't try to compress a read-only keybox. [T6811]
|
||||
|
||||
* gpg: Choose key from inserted card over a non-inserted
|
||||
card. [T6831]
|
||||
|
||||
* gpg: Allow to create revocations even with non-compliant algos.
|
||||
[T6929]
|
||||
|
||||
* gpg: Fix regression in the Revoker keyword of the parameter file.
|
||||
[T6923]
|
||||
|
||||
* gpg: Improve error message for expired default keys. [T4704]
|
||||
|
||||
* gpgsm: Add --always-trust feature. [T6559]
|
||||
|
||||
* gpgsm: Support ECC certificates in de-vs mode. [T6802]
|
||||
|
||||
* gpgsm: Major rewrite of the PKCS#12 parser. [T6536]
|
||||
|
||||
* gpgsm: No not show the pkcs#12 passphrase in debug output. [T6654]
|
||||
|
||||
* keyboxd: Timeout on failure to get the database lock. [T6838]
|
||||
|
||||
* agent: Update the key stubs only if really modified. [T6829]
|
||||
|
||||
* scd: Add support for certain Starcos 3.2 cards. [rG5304c9b080]
|
||||
|
||||
* scd: Add support for CardOS 5.4 cards. [rG812f988059]
|
||||
|
||||
* scd: Add support for D-Trust 4.1/4.4 cards. [rG0b85a9ac09]
|
||||
|
||||
* scd: Add support for Smartcafe Expert 7.0 cards. [T6919]
|
||||
|
||||
* scd: Add a length check for a new PIN. [T6843]
|
||||
|
||||
* tpm: Fix keytotpm handling in the agent. [rG9909f622f6]
|
||||
|
||||
* tpm: Fixes for the TPM test suite. [T6052]
|
||||
|
||||
* dirmngr: Avoid starting a second instance on Windows via GPGME
|
||||
based launching. [T6833]
|
||||
|
||||
* dirmngr: New option --ignore-crl-extensions. [T6545]
|
||||
|
||||
* dirmngr: Support config value "none" to disable the default
|
||||
keyserver. [T6708]
|
||||
|
||||
* dirmngr: Implement automatic proxy detection on Windows. [T5768]
|
||||
|
||||
* dirmngr: Fix handling of the HTTP Content-Length. [rGa5e33618f4]
|
||||
|
||||
* dirmngr: Add code to support proxy authentication using the
|
||||
Negotiation method on Windows. [T6719]
|
||||
|
||||
* gpgconf: Add commands --lock and --unlock. [rG93b5ba38dc]
|
||||
|
||||
* gpgconf: Add keyword socketdir to gpgconf.ctl. [rG239c1fdc28]
|
||||
|
||||
* gpgconf: Adjust the -X command for the new VERSION file format.
|
||||
[T6918]
|
||||
|
||||
* wkd: Use export-clean for gpg-wks-client's --mirror and --create
|
||||
commands. [rG2c7f7a5a278c]
|
||||
|
||||
* wkd: Make --add-revocs the default in gpg-wks-client. New option
|
||||
--no-add-revocs. [rG10c937ee68]
|
||||
|
||||
* Remove duplicated backslashes when setting the homedir. [T6833]
|
||||
|
||||
* Ignore attempts to remove the /dev/null device. [T6556]
|
||||
|
||||
* Improve advisory file lock retry strategy. [T3380]
|
||||
|
||||
* Improve the speedo build system for Unix. [T6710]
|
||||
|
||||
* Fix garbled time output in non-English Windows. [T6741]
|
||||
|
||||
Changes also found in 2.4.3:
|
||||
|
||||
@ -21,6 +116,8 @@ Noteworthy changes in version 2.5.0 (unreleased)
|
||||
|
||||
* gpg: New option --no-compress as alias for -z0.
|
||||
|
||||
* gpg: Show better error messages for blocked PINs. [T6425]
|
||||
|
||||
* gpgsm: Print PROGRESS status lines. Add new --input-size-hint.
|
||||
[T6534]
|
||||
|
||||
@ -52,6 +149,9 @@ Noteworthy changes in version 2.5.0 (unreleased)
|
||||
* scd: Fix authentication with Administration Key for PIV.
|
||||
[rG25b59cf6ce]
|
||||
|
||||
* Fix garbled time output in non-English Windows. [T6741]
|
||||
|
||||
|
||||
Changes also found in 2.4.2:
|
||||
|
||||
* gpg: Print a warning if no more encryption subkeys are left over
|
||||
@ -78,7 +178,7 @@ Noteworthy changes in version 2.5.0 (unreleased)
|
||||
Release dates of 2.4 versions
|
||||
-----------------------------
|
||||
|
||||
Version 2.4.4 (unreleased) https://dev.gnupg.org/T6578
|
||||
Version 2.4.4 (2024-01-25) https://dev.gnupg.org/T6578
|
||||
Version 2.4.3 (2023-07-04) https://dev.gnupg.org/T6509
|
||||
Version 2.4.2 (2023-05-30) https://dev.gnupg.org/T6506
|
||||
Version 2.4.1 (2023-04-28) https://dev.gnupg.org/T6454
|
||||
@ -1678,6 +1778,7 @@ Noteworthy changes in version 2.3.0 (2021-04-07)
|
||||
Release dates of 2.2 versions
|
||||
-----------------------------
|
||||
|
||||
Version 2.2.42 (2023-11-28) https://dev.gnupg.org/T6307
|
||||
Version 2.2.41 (2022-12-09) https://dev.gnupg.org/T6280
|
||||
Version 2.2.40 (2022-10-10) https://dev.gnupg.org/T6181
|
||||
Version 2.2.39 (2022-09-02) https://dev.gnupg.org/T6175
|
||||
|
25
README
25
README
@ -4,7 +4,7 @@
|
||||
|
||||
Copyright 1997-2019 Werner Koch
|
||||
Copyright 1998-2021 Free Software Foundation, Inc.
|
||||
Copyright 2003-2023 g10 Code GmbH
|
||||
Copyright 2003-2024 g10 Code GmbH
|
||||
|
||||
|
||||
* INTRODUCTION
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
Several other standard libraries are also required. The configure
|
||||
script prints diagnostic messages if one of these libraries is not
|
||||
available and a feature will not be available..
|
||||
available and a feature will not be available.
|
||||
|
||||
You also need the Pinentry package for most functions of GnuPG;
|
||||
however it is not a build requirement. Pinentry is available at
|
||||
@ -80,15 +80,24 @@
|
||||
|
||||
to view the directories used by GnuPG.
|
||||
|
||||
** Quick build method on Unix
|
||||
|
||||
To quickly build all required software without installing it, the
|
||||
Speedo method may be used:
|
||||
Speedo target may be used:
|
||||
|
||||
cd build
|
||||
make -f ../build-aux/speedo.mk native
|
||||
make -f build-aux/speedo.mk native
|
||||
|
||||
This target downloads all required libraries and does a native build
|
||||
of GnuPG to PLAY/inst/. GNU make and the patchelf tool are
|
||||
required. After the build the entire software including all
|
||||
libraries can be installed into an arbitrary location using for
|
||||
example:
|
||||
|
||||
make -f build-aux/speedo.mk install SYSROOT=/usr/local/gnupg24
|
||||
ldconfig -n /usr/local/gnupg24/lib
|
||||
|
||||
and adding /usr/local/gnupg24/bin to PATH.
|
||||
|
||||
This method downloads all required libraries and does a native build
|
||||
of GnuPG to PLAY/inst/. GNU make is required and you need to set
|
||||
LD_LIBRARY_PATH to $(pwd)/PLAY/inst/lib to test the binaries.
|
||||
|
||||
** Specific build problems on some machines:
|
||||
|
||||
|
@ -225,6 +225,17 @@ typedef struct ssh_control_file_s *ssh_control_file_t;
|
||||
/* Forward reference for local definitions in call-scd.c. */
|
||||
struct daemon_local_s;
|
||||
|
||||
/* Object to hold ephemeral secret keys. */
|
||||
struct ephemeral_private_key_s
|
||||
{
|
||||
struct ephemeral_private_key_s *next;
|
||||
unsigned char grip[KEYGRIP_LEN];
|
||||
unsigned char *keybuf; /* Canon-s-exp with the private key (malloced). */
|
||||
size_t keybuflen;
|
||||
};
|
||||
typedef struct ephemeral_private_key_s *ephemeral_private_key_t;
|
||||
|
||||
|
||||
/* Collection of data per session (aka connection). */
|
||||
struct server_control_s
|
||||
{
|
||||
@ -246,6 +257,12 @@ struct server_control_s
|
||||
/* Private data of the daemon (call-XXX.c). */
|
||||
struct daemon_local_s *d_local[DAEMON_MAX_TYPE];
|
||||
|
||||
/* Linked list with ephemeral stored private keys. */
|
||||
ephemeral_private_key_t ephemeral_keys;
|
||||
|
||||
/* If set functions will lookup keys in the ephemeral_keys list. */
|
||||
int ephemeral_mode;
|
||||
|
||||
/* Environment settings for the connection. */
|
||||
session_env_t session_env;
|
||||
char *lc_ctype;
|
||||
@ -453,7 +470,8 @@ void start_command_handler_ssh (ctrl_t, gnupg_fd_t);
|
||||
/*-- findkey.c --*/
|
||||
gpg_error_t agent_modify_description (const char *in, const char *comment,
|
||||
const gcry_sexp_t key, char **result);
|
||||
gpg_error_t agent_write_private_key (const unsigned char *grip,
|
||||
gpg_error_t agent_write_private_key (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
const void *buffer, size_t length,
|
||||
int force,
|
||||
const char *serialno, const char *keyref,
|
||||
@ -478,7 +496,7 @@ gpg_error_t agent_ssh_key_from_file (ctrl_t ctrl,
|
||||
gcry_sexp_t *result, int *r_order);
|
||||
int agent_pk_get_algo (gcry_sexp_t s_key);
|
||||
int agent_is_tpm2_key(gcry_sexp_t s_key);
|
||||
int agent_key_available (const unsigned char *grip);
|
||||
int agent_key_available (ctrl_t ctrl, const unsigned char *grip);
|
||||
gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
int *r_keytype,
|
||||
unsigned char **r_shadow_info,
|
||||
@ -486,7 +504,8 @@ gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
gpg_error_t agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
||||
const unsigned char *grip,
|
||||
int force, int only_stubs);
|
||||
gpg_error_t agent_update_private_key (const unsigned char *grip, nvc_t pk);
|
||||
gpg_error_t agent_update_private_key (ctrl_t ctrl,
|
||||
const unsigned char *grip, nvc_t pk);
|
||||
|
||||
/*-- call-pinentry.c --*/
|
||||
void initialize_module_call_pinentry (void);
|
||||
@ -542,15 +561,21 @@ gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
#define CHECK_CONSTRAINTS_NOT_EMPTY 1
|
||||
#define CHECK_CONSTRAINTS_NEW_SYMKEY 2
|
||||
|
||||
#define GENKEY_FLAG_NO_PROTECTION 1
|
||||
#define GENKEY_FLAG_PRESET 2
|
||||
|
||||
void clear_ephemeral_keys (ctrl_t ctrl);
|
||||
|
||||
int check_passphrase_constraints (ctrl_t ctrl, const char *pw,
|
||||
unsigned int flags,
|
||||
char **failed_constraint);
|
||||
gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
|
||||
char **r_passphrase);
|
||||
int agent_genkey (ctrl_t ctrl, const char *cache_nonce, time_t timestamp,
|
||||
int agent_genkey (ctrl_t ctrl, unsigned int flags,
|
||||
const char *cache_nonce, time_t timestamp,
|
||||
const char *keyparam, size_t keyparmlen,
|
||||
int no_protection, const char *override_passphrase,
|
||||
int preset, membuf_t *outbuf);
|
||||
const char *override_passphrase,
|
||||
membuf_t *outbuf);
|
||||
gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
|
||||
char **passphrase_addr);
|
||||
|
||||
@ -588,7 +613,7 @@ gpg_error_t s2k_hash_passphrase (const char *passphrase, int hashalgo,
|
||||
const unsigned char *s2ksalt,
|
||||
unsigned int s2kcount,
|
||||
unsigned char *key, size_t keylen);
|
||||
gpg_error_t agent_write_shadow_key (const unsigned char *grip,
|
||||
gpg_error_t agent_write_shadow_key (ctrl_t ctrl, const unsigned char *grip,
|
||||
const char *serialno, const char *keyid,
|
||||
const unsigned char *pkbuf, int force,
|
||||
const char *dispserialno);
|
||||
|
@ -2430,14 +2430,14 @@ card_key_available (ctrl_t ctrl, const struct card_key_info_s *keyinfo,
|
||||
}
|
||||
|
||||
hex2bin (keyinfo->keygrip, grip, sizeof (grip));
|
||||
if ( agent_key_available (grip) )
|
||||
if (!ctrl->ephemeral_mode && agent_key_available (ctrl, grip) )
|
||||
{
|
||||
char *dispserialno;
|
||||
|
||||
/* (Shadow)-key is not available in our key storage. */
|
||||
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno,
|
||||
keyinfo->keygrip);
|
||||
err = agent_write_shadow_key (grip, keyinfo->serialno,
|
||||
err = agent_write_shadow_key (ctrl, grip, keyinfo->serialno,
|
||||
keyinfo->idstr, pkbuf, 0, dispserialno);
|
||||
xfree (dispserialno);
|
||||
if (err)
|
||||
@ -3222,7 +3222,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
|
||||
|
||||
/* Check whether the key is already in our key storage. Don't do
|
||||
anything then besides (re-)adding it to sshcontrol. */
|
||||
if ( !agent_key_available (key_grip_raw) )
|
||||
if ( !agent_key_available (ctrl, key_grip_raw) )
|
||||
goto key_exists; /* Yes, key is available. */
|
||||
|
||||
err = ssh_key_extract_comment (key, &comment);
|
||||
@ -3286,7 +3286,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
|
||||
|
||||
/* Store this key to our key storage. We do not store a creation
|
||||
* timestamp because we simply do not know. */
|
||||
err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0,
|
||||
err = agent_write_private_key (ctrl, key_grip_raw, buffer, buffer_n, 0,
|
||||
NULL, NULL, NULL, 0);
|
||||
if (err)
|
||||
goto out;
|
||||
|
109
agent/command.c
109
agent/command.c
@ -251,6 +251,9 @@ reset_notify (assuan_context_t ctx, char *line)
|
||||
|
||||
clear_nonce_cache (ctrl);
|
||||
|
||||
/* Note that a RESET does not clear the ephemeral store becuase
|
||||
* clients are used to issue a RESET on a connection. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -634,34 +637,65 @@ cmd_marktrusted (assuan_context_t ctx, char *line)
|
||||
static const char hlp_havekey[] =
|
||||
"HAVEKEY <hexstrings_with_keygrips>\n"
|
||||
"HAVEKEY --list[=<limit>]\n"
|
||||
"HAVEKEY --info <hexkeygrip>\n"
|
||||
"\n"
|
||||
"Return success if at least one of the secret keys with the given\n"
|
||||
"keygrips is available. With --list return all available keygrips\n"
|
||||
"as binary data; with <limit> bail out at this number of keygrips";
|
||||
"as binary data; with <limit> bail out at this number of keygrips.\n"
|
||||
"In --info mode check just one keygrip.";
|
||||
static gpg_error_t
|
||||
cmd_havekey (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl;
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err;
|
||||
unsigned char grip[20];
|
||||
char *p;
|
||||
int list_mode; /* Less than 0 for no limit. */
|
||||
int list_mode = 0; /* Less than 0 for no limit. */
|
||||
int info_mode = 0;
|
||||
int counter;
|
||||
char *dirname;
|
||||
gnupg_dir_t dir;
|
||||
char *dirname = NULL;
|
||||
gnupg_dir_t dir = NULL;
|
||||
gnupg_dirent_t dir_entry;
|
||||
char hexgrip[41];
|
||||
struct card_key_info_s *keyinfo_on_cards, *l;
|
||||
|
||||
if (has_option_name (line, "--list"))
|
||||
if (has_option (line, "--info"))
|
||||
info_mode = 1;
|
||||
else if (has_option_name (line, "--list"))
|
||||
{
|
||||
if ((p = option_value (line, "--list")))
|
||||
list_mode = atoi (p);
|
||||
else
|
||||
list_mode = -1;
|
||||
}
|
||||
else
|
||||
list_mode = 0;
|
||||
|
||||
line = skip_options (line);
|
||||
|
||||
if (info_mode)
|
||||
{
|
||||
int keytype;
|
||||
const char *infostring;
|
||||
|
||||
err = parse_keygrip (ctx, line, grip);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
err = agent_key_info_from_file (ctrl, grip, &keytype, NULL, NULL);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
switch (keytype)
|
||||
{
|
||||
case PRIVATE_KEY_CLEAR:
|
||||
case PRIVATE_KEY_OPENPGP_NONE: infostring = "clear"; break;
|
||||
case PRIVATE_KEY_PROTECTED: infostring = "protected"; break;
|
||||
case PRIVATE_KEY_SHADOWED: infostring = "shadowed"; break;
|
||||
default: infostring = "unknown"; break;
|
||||
}
|
||||
|
||||
err = agent_write_status (ctrl, "KEYFILEINFO", infostring, NULL);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
||||
if (!list_mode)
|
||||
@ -672,7 +706,7 @@ cmd_havekey (assuan_context_t ctx, char *line)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!agent_key_available (grip))
|
||||
if (!agent_key_available (ctrl, grip))
|
||||
return 0; /* Found. */
|
||||
|
||||
while (*line && *line != ' ' && *line != '\t')
|
||||
@ -690,7 +724,6 @@ cmd_havekey (assuan_context_t ctx, char *line)
|
||||
/* List mode. */
|
||||
dir = NULL;
|
||||
dirname = NULL;
|
||||
ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
if (ctrl->restricted)
|
||||
{
|
||||
@ -1083,26 +1116,27 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
int no_protection;
|
||||
unsigned char *value = NULL;
|
||||
size_t valuelen;
|
||||
unsigned char *newpasswd = NULL;
|
||||
membuf_t outbuf;
|
||||
char *cache_nonce = NULL;
|
||||
char *passwd_nonce = NULL;
|
||||
int opt_preset;
|
||||
int opt_inq_passwd;
|
||||
size_t n;
|
||||
char *p, *pend;
|
||||
const char *s;
|
||||
time_t opt_timestamp;
|
||||
int c;
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (ctrl->restricted)
|
||||
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
|
||||
|
||||
no_protection = has_option (line, "--no-protection");
|
||||
opt_preset = has_option (line, "--preset");
|
||||
if (has_option (line, "--no-protection"))
|
||||
flags |= GENKEY_FLAG_NO_PROTECTION;
|
||||
if (has_option (line, "--preset"))
|
||||
flags |= GENKEY_FLAG_PRESET;
|
||||
opt_inq_passwd = has_option (line, "--inq-passwd");
|
||||
passwd_nonce = option_value (line, "--passwd-nonce");
|
||||
if (passwd_nonce)
|
||||
@ -1157,7 +1191,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
||||
|
||||
/* If requested, ask for the password to be used for the key. If
|
||||
this is not used the regular Pinentry mechanism is used. */
|
||||
if (opt_inq_passwd && !no_protection)
|
||||
if (opt_inq_passwd && !(flags & GENKEY_FLAG_NO_PROTECTION))
|
||||
{
|
||||
/* (N is used as a dummy) */
|
||||
assuan_begin_confidential (ctx);
|
||||
@ -1170,16 +1204,17 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
||||
/* Empty password given - switch to no-protection mode. */
|
||||
xfree (newpasswd);
|
||||
newpasswd = NULL;
|
||||
no_protection = 1;
|
||||
flags |= GENKEY_FLAG_NO_PROTECTION;
|
||||
}
|
||||
|
||||
}
|
||||
else if (passwd_nonce)
|
||||
newpasswd = agent_get_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE);
|
||||
|
||||
rc = agent_genkey (ctrl, cache_nonce, opt_timestamp,
|
||||
(char*)value, valuelen, no_protection,
|
||||
newpasswd, opt_preset, &outbuf);
|
||||
|
||||
rc = agent_genkey (ctrl, flags, cache_nonce, opt_timestamp,
|
||||
(char*)value, valuelen,
|
||||
newpasswd, &outbuf);
|
||||
|
||||
leave:
|
||||
if (newpasswd)
|
||||
@ -1283,7 +1318,7 @@ cmd_keyattr (assuan_context_t ctx, char *line)
|
||||
if (!err)
|
||||
err = nvc_set_private_key (keymeta, s_key);
|
||||
if (!err)
|
||||
err = agent_update_private_key (grip, keymeta);
|
||||
err = agent_update_private_key (ctrl, grip, keymeta);
|
||||
}
|
||||
|
||||
nvc_release (keymeta);
|
||||
@ -1293,6 +1328,8 @@ cmd_keyattr (assuan_context_t ctx, char *line)
|
||||
leave:
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char hlp_readkey[] =
|
||||
"READKEY [--no-data] [--format=ssh] <hexstring_with_keygrip>\n"
|
||||
@ -1356,7 +1393,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (agent_key_available (grip))
|
||||
if (!ctrl->ephemeral_mode && agent_key_available (ctrl, grip))
|
||||
{
|
||||
/* (Shadow)-key is not available in our key storage. */
|
||||
char *dispserialno;
|
||||
@ -1364,7 +1401,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno, hexgrip);
|
||||
rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0,
|
||||
rc = agent_write_shadow_key (ctrl, grip, serialno, keyid, pkbuf, 0,
|
||||
dispserialno);
|
||||
xfree (dispserialno);
|
||||
if (rc)
|
||||
@ -2900,7 +2937,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!force && !agent_key_available (grip))
|
||||
if (!force && !agent_key_available (ctrl, grip))
|
||||
err = gpg_error (GPG_ERR_EEXIST);
|
||||
else
|
||||
{
|
||||
@ -2922,11 +2959,11 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
||||
err = agent_protect (key, passphrase, &finalkey, &finalkeylen,
|
||||
ctrl->s2k_count);
|
||||
if (!err)
|
||||
err = agent_write_private_key (grip, finalkey, finalkeylen, force,
|
||||
err = agent_write_private_key (ctrl, grip, finalkey, finalkeylen, force,
|
||||
NULL, NULL, NULL, opt_timestamp);
|
||||
}
|
||||
else
|
||||
err = agent_write_private_key (grip, key, realkeylen, force,
|
||||
err = agent_write_private_key (ctrl, grip, key, realkeylen, force,
|
||||
NULL, NULL, NULL, opt_timestamp);
|
||||
|
||||
leave:
|
||||
@ -2945,7 +2982,8 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
||||
|
||||
|
||||
static const char hlp_export_key[] =
|
||||
"EXPORT_KEY [--cache-nonce=<nonce>] [--openpgp|--mode1003] <hexkeygrip>\n"
|
||||
"EXPORT_KEY [--cache-nonce=<nonce>] \\\n"
|
||||
" [--openpgp|--mode1003] <hexkeygrip>\n"
|
||||
"\n"
|
||||
"Export a secret key from the key store. The key will be encrypted\n"
|
||||
"using the current session's key wrapping key (cf. command KEYWRAP_KEY)\n"
|
||||
@ -2953,8 +2991,8 @@ static const char hlp_export_key[] =
|
||||
"prior to using this command. The function takes the keygrip as argument.\n"
|
||||
"\n"
|
||||
"If --openpgp is used, the secret key material will be exported in RFC 4880\n"
|
||||
"compatible passphrase-protected form. If --mode1003 is use the secret key\n"
|
||||
"is exported as s-expression as storred locally. Without those options,\n"
|
||||
"compatible passphrase-protected form. In --mode1003 the secret key\n"
|
||||
"is exported as s-expression as stored locally. Without those options,\n"
|
||||
"the secret key material will be exported in the clear (after prompting\n"
|
||||
"the user to unlock it, if needed).\n";
|
||||
static gpg_error_t
|
||||
@ -3011,7 +3049,7 @@ cmd_export_key (assuan_context_t ctx, char *line)
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
if (agent_key_available (grip))
|
||||
if (agent_key_available (ctrl, grip))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
goto leave;
|
||||
@ -3223,7 +3261,7 @@ cmd_keytocard (assuan_context_t ctx, char *line)
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
if (agent_key_available (grip))
|
||||
if (agent_key_available (ctrl, grip))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
goto leave;
|
||||
@ -3543,7 +3581,7 @@ cmd_keytotpm (assuan_context_t ctx, char *line)
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
if (agent_key_available (grip))
|
||||
if (agent_key_available (ctrl, grip))
|
||||
{
|
||||
err =gpg_error (GPG_ERR_NO_SECKEY);
|
||||
goto leave;
|
||||
@ -3835,6 +3873,7 @@ static const char hlp_getinfo[] =
|
||||
" getenv NAME - Return value of envvar NAME.\n"
|
||||
" connections - Return number of active connections.\n"
|
||||
" jent_active - Returns OK if Libgcrypt's JENT is active.\n"
|
||||
" ephemeral - Returns OK if the connection is in ephemeral mode.\n"
|
||||
" restricted - Returns OK if the connection is in restricted mode.\n"
|
||||
" cmd_has_option CMD OPT\n"
|
||||
" - Returns OK if command CMD has option OPT.\n";
|
||||
@ -3888,6 +3927,10 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
||||
snprintf (numbuf, sizeof numbuf, "%lu", get_standard_s2k_count ());
|
||||
rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
|
||||
}
|
||||
else if (!strcmp (line, "ephemeral"))
|
||||
{
|
||||
rc = ctrl->ephemeral_mode? 0 : gpg_error (GPG_ERR_FALSE);
|
||||
}
|
||||
else if (!strcmp (line, "restricted"))
|
||||
{
|
||||
rc = ctrl->restricted? 0 : gpg_error (GPG_ERR_FALSE);
|
||||
@ -4044,6 +4087,10 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
|
||||
ctrl->server_local->allow_fully_canceled =
|
||||
gnupg_compare_version (value, "2.1.0");
|
||||
}
|
||||
else if (!strcmp (key, "ephemeral"))
|
||||
{
|
||||
ctrl->ephemeral_mode = *value? atoi (value) : 0;
|
||||
}
|
||||
else if (ctrl->restricted)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_FORBIDDEN);
|
||||
|
@ -969,7 +969,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, int dontcare_exist,
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
if (!dontcare_exist && !from_native && !agent_key_available (grip))
|
||||
if (!dontcare_exist && !from_native && !agent_key_available (ctrl, grip))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_EEXIST);
|
||||
goto leave;
|
||||
@ -1147,14 +1147,16 @@ convert_from_openpgp_native (ctrl_t ctrl,
|
||||
if (!agent_protect (*r_key, passphrase,
|
||||
&protectedkey, &protectedkeylen,
|
||||
ctrl->s2k_count))
|
||||
agent_write_private_key (grip, protectedkey, protectedkeylen, 1,
|
||||
NULL, NULL, NULL, 0);
|
||||
agent_write_private_key (ctrl, grip,
|
||||
protectedkey,
|
||||
protectedkeylen,
|
||||
1, NULL, NULL, NULL, 0);
|
||||
xfree (protectedkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Empty passphrase: write key without protection. */
|
||||
agent_write_private_key (grip,
|
||||
agent_write_private_key (ctrl, grip,
|
||||
*r_key,
|
||||
gcry_sexp_canon_len (*r_key, 0, NULL,NULL),
|
||||
1, NULL, NULL, NULL, 0);
|
||||
|
@ -57,7 +57,7 @@ agent_write_tpm2_shadow_key (ctrl_t ctrl, const unsigned char *grip,
|
||||
}
|
||||
|
||||
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
|
||||
err = agent_write_private_key (grip, shdkey, len, 1 /*force*/,
|
||||
err = agent_write_private_key (ctrl, grip, shdkey, len, 1 /*force*/,
|
||||
NULL, NULL, NULL, 0);
|
||||
xfree (shdkey);
|
||||
if (err)
|
||||
@ -70,7 +70,7 @@ agent_write_tpm2_shadow_key (ctrl_t ctrl, const unsigned char *grip,
|
||||
return GPG_ERR_ENOMEM;
|
||||
|
||||
gcry_sexp_sprint(s_key, GCRYSEXP_FMT_CANON, pkbuf, len);
|
||||
err1 = agent_write_private_key (grip, pkbuf, len, 1 /*force*/,
|
||||
err1 = agent_write_private_key (ctrl, grip, pkbuf, len, 1 /*force*/,
|
||||
NULL, NULL, NULL, 0);
|
||||
xfree(pkbuf);
|
||||
if (err1)
|
||||
|
300
agent/findkey.c
300
agent/findkey.c
@ -40,7 +40,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
static gpg_error_t read_key_file (const unsigned char *grip,
|
||||
static gpg_error_t read_key_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t *result, nvc_t *r_keymeta,
|
||||
char **r_orig_key_value);
|
||||
static gpg_error_t is_shadowed_key (gcry_sexp_t s_skey);
|
||||
@ -73,6 +73,30 @@ fname_from_keygrip (const unsigned char *grip, int for_new)
|
||||
}
|
||||
|
||||
|
||||
/* Helper until we have a "wipe" mode flag in es_fopen. */
|
||||
static void
|
||||
wipe_and_fclose (estream_t fp)
|
||||
{
|
||||
void *blob;
|
||||
size_t blob_size;
|
||||
|
||||
if (!fp)
|
||||
;
|
||||
else if (es_fclose_snatch (fp, &blob, &blob_size))
|
||||
{
|
||||
log_error ("error wiping buffer during fclose\n");
|
||||
es_fclose (fp);
|
||||
}
|
||||
else if (blob)
|
||||
{
|
||||
wipememory (blob, blob_size);
|
||||
gpgrt_free (blob);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Replace all linefeeds in STRING by "%0A" and return a new malloced
|
||||
* string. May return NULL on memory error. */
|
||||
static char *
|
||||
@ -110,7 +134,8 @@ linefeed_to_percent0A (const char *string)
|
||||
* TIMESTAMP is not zero and the key does not yet exists it will be
|
||||
* recorded as creation date. */
|
||||
gpg_error_t
|
||||
agent_write_private_key (const unsigned char *grip,
|
||||
agent_write_private_key (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
const void *buffer, size_t length, int force,
|
||||
const char *serialno, const char *keyref,
|
||||
const char *dispserialno,
|
||||
@ -120,7 +145,7 @@ agent_write_private_key (const unsigned char *grip,
|
||||
char *fname = NULL;
|
||||
char *tmpfname = NULL;
|
||||
estream_t fp = NULL;
|
||||
int newkey;
|
||||
int newkey = 0;
|
||||
nvc_t pk = NULL;
|
||||
gcry_sexp_t key = NULL;
|
||||
int removetmp = 0;
|
||||
@ -134,11 +159,13 @@ agent_write_private_key (const unsigned char *grip,
|
||||
const char *s;
|
||||
int force_modify = 0;
|
||||
|
||||
fname = fname_from_keygrip (grip, 0);
|
||||
fname = (ctrl->ephemeral_mode
|
||||
? xtrystrdup ("[ephemeral key store]")
|
||||
: fname_from_keygrip (grip, 0));
|
||||
if (!fname)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
err = read_key_file (grip, &key, &pk, &orig_key_value);
|
||||
err = read_key_file (ctrl, grip, &key, &pk, &orig_key_value);
|
||||
if (err)
|
||||
{
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
@ -289,6 +316,61 @@ agent_write_private_key (const unsigned char *grip,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (ctrl->ephemeral_mode)
|
||||
{
|
||||
ephemeral_private_key_t ek;
|
||||
void *blob;
|
||||
size_t blobsize;
|
||||
|
||||
for (ek = ctrl->ephemeral_keys; ek; ek = ek->next)
|
||||
if (!memcmp (ek->grip, grip, KEYGRIP_LEN))
|
||||
break;
|
||||
if (!ek)
|
||||
{
|
||||
ek = xtrycalloc (1, sizeof *ek);
|
||||
if (!ek)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
memcpy (ek->grip, grip, KEYGRIP_LEN);
|
||||
ek->next = ctrl->ephemeral_keys;
|
||||
ctrl->ephemeral_keys = ek;
|
||||
}
|
||||
|
||||
fp = es_fopenmem (0, "wb,wipe");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("can't open memory stream: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = nvc_write (pk, fp);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error writing to memory stream: %s\n",gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (es_fclose_snatch (fp, &blob, &blobsize) || !blob)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error getting memory stream buffer: %s\n",
|
||||
gpg_strerror (err));
|
||||
/* Closing right away so that we don't try another snatch in
|
||||
* the cleanup. */
|
||||
es_fclose (fp);
|
||||
fp = NULL;
|
||||
goto leave;
|
||||
}
|
||||
fp = NULL;
|
||||
xfree (ek->keybuf);
|
||||
ek->keybuf = blob;
|
||||
ek->keybuflen = blobsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a temporary file for writing. */
|
||||
tmpfname = fname_from_keygrip (grip, 1);
|
||||
fp = tmpfname ? es_fopen (tmpfname, "wbx,mode=-rw") : NULL;
|
||||
@ -327,12 +409,16 @@ agent_write_private_key (const unsigned char *grip,
|
||||
removetmp = 1;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
bump_key_eventcounter ();
|
||||
|
||||
leave:
|
||||
if (blocksigs)
|
||||
gnupg_unblock_all_signals ();
|
||||
if (ctrl->ephemeral_mode)
|
||||
wipe_and_fclose (fp);
|
||||
else
|
||||
es_fclose (fp);
|
||||
if (removetmp && tmpfname)
|
||||
gnupg_remove (tmpfname);
|
||||
@ -350,7 +436,7 @@ agent_write_private_key (const unsigned char *grip,
|
||||
|
||||
|
||||
gpg_error_t
|
||||
agent_update_private_key (const unsigned char *grip, nvc_t pk)
|
||||
agent_update_private_key (ctrl_t ctrl, const unsigned char *grip, nvc_t pk)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char *fname0 = NULL; /* The existing file name. */
|
||||
@ -359,6 +445,57 @@ agent_update_private_key (const unsigned char *grip, nvc_t pk)
|
||||
int removetmp = 0;
|
||||
int blocksigs = 0;
|
||||
|
||||
if (ctrl->ephemeral_mode)
|
||||
{
|
||||
ephemeral_private_key_t ek;
|
||||
void *blob;
|
||||
size_t blobsize;
|
||||
|
||||
for (ek = ctrl->ephemeral_keys; ek; ek = ek->next)
|
||||
if (!memcmp (ek->grip, grip, KEYGRIP_LEN))
|
||||
break;
|
||||
if (!ek)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_ENOENT);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
fp = es_fopenmem (0, "wbx,wipe");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("can't open memory stream: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = nvc_write (pk, fp);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error writing to memory stream: %s\n",gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (es_fclose_snatch (fp, &blob, &blobsize) || !blob)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error getting memory stream buffer: %s\n",
|
||||
gpg_strerror (err));
|
||||
/* Closing right away so that we don't try another snatch in
|
||||
* the cleanup. */
|
||||
es_fclose (fp);
|
||||
fp = NULL;
|
||||
goto leave;
|
||||
}
|
||||
fp = NULL;
|
||||
/* No need to revisit the linked list because the found EK is
|
||||
* not expected to change due to the other syscalls above. */
|
||||
xfree (ek->keybuf);
|
||||
ek->keybuf = blob;
|
||||
ek->keybuflen = blobsize;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
||||
fname0 = fname_from_keygrip (grip, 0);
|
||||
if (!fname0)
|
||||
{
|
||||
@ -404,6 +541,9 @@ agent_update_private_key (const unsigned char *grip, nvc_t pk)
|
||||
leave:
|
||||
if (blocksigs)
|
||||
gnupg_unblock_all_signals ();
|
||||
if (ctrl->ephemeral_mode)
|
||||
wipe_and_fclose (fp);
|
||||
else
|
||||
es_fclose (fp);
|
||||
if (removetmp && fname)
|
||||
gnupg_remove (fname);
|
||||
@ -888,17 +1028,17 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
||||
* caller must free it. On failure returns an error code and stores
|
||||
* NULL at RESULT and R_KEYMETA. */
|
||||
static gpg_error_t
|
||||
read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta,
|
||||
char **r_orig_key_value)
|
||||
read_key_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t *result, nvc_t *r_keymeta, char **r_orig_key_value)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char *fname;
|
||||
estream_t fp;
|
||||
struct stat st;
|
||||
unsigned char *buf;
|
||||
estream_t fp = NULL;
|
||||
unsigned char *buf = NULL;
|
||||
size_t buflen, erroff;
|
||||
gcry_sexp_t s_skey;
|
||||
nvc_t pk = NULL;
|
||||
char first;
|
||||
size_t keybuflen;
|
||||
|
||||
*result = NULL;
|
||||
if (r_keymeta)
|
||||
@ -906,19 +1046,42 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta,
|
||||
if (r_orig_key_value)
|
||||
*r_orig_key_value = NULL;
|
||||
|
||||
fname = fname_from_keygrip (grip, 0);
|
||||
fname = (ctrl->ephemeral_mode
|
||||
? xtrystrdup ("[ephemeral key store]")
|
||||
: fname_from_keygrip (grip, 0));
|
||||
if (!fname)
|
||||
{
|
||||
return gpg_error_from_syserror ();
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (ctrl->ephemeral_mode)
|
||||
{
|
||||
ephemeral_private_key_t ek;
|
||||
|
||||
for (ek = ctrl->ephemeral_keys; ek; ek = ek->next)
|
||||
if (!memcmp (ek->grip, grip, KEYGRIP_LEN)
|
||||
&& ek->keybuf && ek->keybuflen)
|
||||
break;
|
||||
if (!ek || !ek->keybuf || !ek->keybuflen)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_ENOENT);
|
||||
goto leave;
|
||||
}
|
||||
keybuflen = ek->keybuflen;
|
||||
fp = es_fopenmem_init (0, "rb", ek->keybuf, ek->keybuflen);
|
||||
}
|
||||
else
|
||||
{
|
||||
keybuflen = 0; /* Indicates that this is not ephemeral mode. */
|
||||
fp = es_fopen (fname, "rb");
|
||||
}
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
if (gpg_err_code (err) != GPG_ERR_ENOENT)
|
||||
log_error ("can't open '%s': %s\n", fname, gpg_strerror (err));
|
||||
xfree (fname);
|
||||
return err;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (es_fread (&first, 1, 1, fp) != 1)
|
||||
@ -926,28 +1089,22 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta,
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error reading first byte from '%s': %s\n",
|
||||
fname, gpg_strerror (err));
|
||||
xfree (fname);
|
||||
es_fclose (fp);
|
||||
return err;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (es_fseek (fp, 0, SEEK_SET))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error seeking in '%s': %s\n", fname, gpg_strerror (err));
|
||||
xfree (fname);
|
||||
es_fclose (fp);
|
||||
return err;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (first != '(')
|
||||
{
|
||||
/* Key is in extended format. */
|
||||
nvc_t pk = NULL;
|
||||
int line;
|
||||
|
||||
err = nvc_parse_private_key (&pk, &line, fp);
|
||||
es_fclose (fp);
|
||||
|
||||
if (err)
|
||||
log_error ("error parsing '%s' line %d: %s\n",
|
||||
@ -969,9 +1126,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta,
|
||||
if (!*r_orig_key_value)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
nvc_release (pk);
|
||||
xfree (fname);
|
||||
return err;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -979,35 +1134,31 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta,
|
||||
}
|
||||
}
|
||||
|
||||
if (!err && r_keymeta)
|
||||
*r_keymeta = pk;
|
||||
else
|
||||
nvc_release (pk);
|
||||
xfree (fname);
|
||||
return err;
|
||||
goto leave; /* Ready. */
|
||||
}
|
||||
|
||||
if (keybuflen)
|
||||
buflen = keybuflen;
|
||||
else
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (fstat (es_fileno (fp), &st))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("can't stat '%s': %s\n", fname, gpg_strerror (err));
|
||||
xfree (fname);
|
||||
es_fclose (fp);
|
||||
return err;
|
||||
goto leave;
|
||||
}
|
||||
buflen = st.st_size;
|
||||
}
|
||||
|
||||
buflen = st.st_size;
|
||||
buf = xtrymalloc (buflen+1);
|
||||
if (!buf)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error allocating %zu bytes for '%s': %s\n",
|
||||
buflen, fname, gpg_strerror (err));
|
||||
xfree (fname);
|
||||
es_fclose (fp);
|
||||
xfree (buf);
|
||||
return err;
|
||||
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (es_fread (buf, buflen, 1, fp) != 1)
|
||||
@ -1015,25 +1166,32 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta,
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error reading %zu bytes from '%s': %s\n",
|
||||
buflen, fname, gpg_strerror (err));
|
||||
xfree (fname);
|
||||
es_fclose (fp);
|
||||
xfree (buf);
|
||||
return err;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Convert the file into a gcrypt S-expression object. */
|
||||
err = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
|
||||
xfree (fname);
|
||||
es_fclose (fp);
|
||||
xfree (buf);
|
||||
if (err)
|
||||
{
|
||||
gcry_sexp_t s_skey;
|
||||
|
||||
err = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
|
||||
if (err)
|
||||
log_error ("failed to build S-Exp (off=%u): %s\n",
|
||||
(unsigned int)erroff, gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
else
|
||||
*result = s_skey;
|
||||
return 0;
|
||||
}
|
||||
|
||||
leave:
|
||||
if (!err && r_keymeta)
|
||||
*r_keymeta = pk;
|
||||
else
|
||||
nvc_release (pk);
|
||||
if (ctrl->ephemeral_mode)
|
||||
wipe_and_fclose (fp);
|
||||
else
|
||||
es_fclose (fp);
|
||||
xfree (fname);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -1226,7 +1384,8 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
||||
if (!grip && !ctrl->have_keygrip)
|
||||
return gpg_error (GPG_ERR_NO_SECKEY);
|
||||
|
||||
err = read_key_file (grip? grip : ctrl->keygrip, &s_skey, &keymeta, NULL);
|
||||
err = read_key_file (ctrl, grip? grip : ctrl->keygrip,
|
||||
&s_skey, &keymeta, NULL);
|
||||
if (err)
|
||||
{
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
@ -1485,7 +1644,7 @@ agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
|
||||
*result = NULL;
|
||||
|
||||
err = read_key_file (grip, &s_skey, r_keymeta, NULL);
|
||||
err = read_key_file (ctrl, grip, &s_skey, r_keymeta, NULL);
|
||||
if (!err)
|
||||
*result = s_skey;
|
||||
return err;
|
||||
@ -1528,7 +1687,7 @@ public_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
if (r_sshorder)
|
||||
*r_sshorder = 0;
|
||||
|
||||
err = read_key_file (grip, &s_skey, for_ssh? &keymeta : NULL, NULL);
|
||||
err = read_key_file (ctrl, grip, &s_skey, for_ssh? &keymeta : NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -1658,11 +1817,21 @@ agent_ssh_key_from_file (ctrl_t ctrl,
|
||||
/* Check whether the secret key identified by GRIP is available.
|
||||
Returns 0 is the key is available. */
|
||||
int
|
||||
agent_key_available (const unsigned char *grip)
|
||||
agent_key_available (ctrl_t ctrl, const unsigned char *grip)
|
||||
{
|
||||
int result;
|
||||
char *fname;
|
||||
char hexgrip[40+4+1];
|
||||
ephemeral_private_key_t ek;
|
||||
|
||||
if (ctrl && ctrl->ephemeral_mode)
|
||||
{
|
||||
for (ek = ctrl->ephemeral_keys; ek; ek = ek->next)
|
||||
if (!memcmp (ek->grip, grip, KEYGRIP_LEN)
|
||||
&& ek->keybuf && ek->keybuflen)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
strcpy (hexgrip+40, ".key");
|
||||
@ -1675,7 +1844,6 @@ agent_key_available (const unsigned char *grip)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Return the information about the secret key specified by the binary
|
||||
keygrip GRIP. If the key is a shadowed one the shadow information
|
||||
will be stored at the address R_SHADOW_INFO as an allocated
|
||||
@ -1700,7 +1868,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
{
|
||||
gcry_sexp_t sexp;
|
||||
|
||||
err = read_key_file (grip, &sexp, NULL, NULL);
|
||||
err = read_key_file (ctrl, grip, &sexp, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
@ -1784,7 +1952,13 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
||||
char *default_desc = NULL;
|
||||
int key_type;
|
||||
|
||||
err = read_key_file (grip, &s_skey, NULL, NULL);
|
||||
if (ctrl->ephemeral_mode)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = read_key_file (ctrl, grip, &s_skey, NULL, NULL);
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
if (err)
|
||||
@ -1885,7 +2059,7 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
||||
card's SERIALNO and the IDSTRING. With FORCE passed as true an
|
||||
existing key with the given GRIP will get overwritten. */
|
||||
gpg_error_t
|
||||
agent_write_shadow_key (const unsigned char *grip,
|
||||
agent_write_shadow_key (ctrl_t ctrl, const unsigned char *grip,
|
||||
const char *serialno, const char *keyid,
|
||||
const unsigned char *pkbuf, int force,
|
||||
const char *dispserialno)
|
||||
@ -1915,7 +2089,7 @@ agent_write_shadow_key (const unsigned char *grip,
|
||||
}
|
||||
|
||||
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
|
||||
err = agent_write_private_key (grip, shdkey, len, force,
|
||||
err = agent_write_private_key (ctrl, grip, shdkey, len, force,
|
||||
serialno, keyid, dispserialno, 0);
|
||||
xfree (shdkey);
|
||||
if (err)
|
||||
|
138
agent/genkey.c
138
agent/genkey.c
@ -30,14 +30,36 @@
|
||||
#include "../common/exechelp.h"
|
||||
#include "../common/sysutils.h"
|
||||
|
||||
static int
|
||||
store_key (gcry_sexp_t private, const char *passphrase, int force,
|
||||
|
||||
void
|
||||
clear_ephemeral_keys (ctrl_t ctrl)
|
||||
{
|
||||
while (ctrl->ephemeral_keys)
|
||||
{
|
||||
ephemeral_private_key_t next = ctrl->ephemeral_keys->next;
|
||||
if (ctrl->ephemeral_keys->keybuf)
|
||||
{
|
||||
wipememory (ctrl->ephemeral_keys->keybuf,
|
||||
ctrl->ephemeral_keys->keybuflen);
|
||||
xfree (ctrl->ephemeral_keys->keybuf);
|
||||
}
|
||||
xfree (ctrl->ephemeral_keys);
|
||||
ctrl->ephemeral_keys = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Store the key either to a file, or in ctrl->ephemeral_mode in the
|
||||
* session data. */
|
||||
static gpg_error_t
|
||||
store_key (ctrl_t ctrl, gcry_sexp_t private,
|
||||
const char *passphrase, int force,
|
||||
unsigned long s2k_count, time_t timestamp)
|
||||
{
|
||||
int rc;
|
||||
gpg_error_t err;
|
||||
unsigned char *buf;
|
||||
size_t len;
|
||||
unsigned char grip[20];
|
||||
unsigned char grip[KEYGRIP_LEN];
|
||||
|
||||
if ( !gcry_pk_get_keygrip (private, grip) )
|
||||
{
|
||||
@ -49,7 +71,10 @@ store_key (gcry_sexp_t private, const char *passphrase, int force,
|
||||
log_assert (len);
|
||||
buf = gcry_malloc_secure (len);
|
||||
if (!buf)
|
||||
return out_of_core ();
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
|
||||
log_assert (len);
|
||||
|
||||
@ -57,20 +82,56 @@ store_key (gcry_sexp_t private, const char *passphrase, int force,
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
rc = agent_protect (buf, passphrase, &p, &len, s2k_count);
|
||||
if (rc)
|
||||
{
|
||||
xfree (buf);
|
||||
return rc;
|
||||
}
|
||||
err = agent_protect (buf, passphrase, &p, &len, s2k_count);
|
||||
if (err)
|
||||
goto leave;
|
||||
xfree (buf);
|
||||
buf = p;
|
||||
}
|
||||
|
||||
rc = agent_write_private_key (grip, buf, len, force,
|
||||
if (ctrl->ephemeral_mode)
|
||||
{
|
||||
ephemeral_private_key_t ek;
|
||||
|
||||
for (ek = ctrl->ephemeral_keys; ek; ek = ek->next)
|
||||
if (!memcmp (ek->grip, grip, KEYGRIP_LEN))
|
||||
break;
|
||||
if (!ek)
|
||||
{
|
||||
ek = xtrycalloc (1, sizeof *ek);
|
||||
if (!ek)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
memcpy (ek->grip, grip, KEYGRIP_LEN);
|
||||
ek->next = ctrl->ephemeral_keys;
|
||||
ctrl->ephemeral_keys = ek;
|
||||
}
|
||||
if (ek->keybuf)
|
||||
{
|
||||
wipememory (ek->keybuf, ek->keybuflen);
|
||||
xfree (ek->keybuf);
|
||||
}
|
||||
ek->keybuf = buf;
|
||||
buf = NULL;
|
||||
ek->keybuflen = len;
|
||||
}
|
||||
else
|
||||
err = agent_write_private_key (ctrl, grip, buf, len, force,
|
||||
NULL, NULL, NULL, timestamp);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
char hexgrip[2*KEYGRIP_LEN+1];
|
||||
|
||||
bin2hex (grip, KEYGRIP_LEN, hexgrip);
|
||||
agent_write_status (ctrl, "KEYGRIP", hexgrip, NULL);
|
||||
}
|
||||
|
||||
leave:
|
||||
xfree (buf);
|
||||
return rc;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -458,16 +519,19 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
|
||||
|
||||
|
||||
/* Generate a new keypair according to the parameters given in
|
||||
KEYPARAM. If CACHE_NONCE is given first try to lookup a passphrase
|
||||
using the cache nonce. If NO_PROTECTION is true the key will not
|
||||
be protected by a passphrase. If OVERRIDE_PASSPHRASE is true that
|
||||
passphrase will be used for the new key. If TIMESTAMP is not zero
|
||||
it will be recorded as creation date of the key (unless extended
|
||||
format is disabled) . */
|
||||
* KEYPARAM. If CACHE_NONCE is given first try to lookup a passphrase
|
||||
* using the cache nonce. If NO_PROTECTION is true the key will not
|
||||
* be protected by a passphrase. If OVERRIDE_PASSPHRASE is true that
|
||||
* passphrase will be used for the new key. If TIMESTAMP is not zero
|
||||
* it will be recorded as creation date of the key (unless extended
|
||||
* format is disabled). In ctrl_ephemeral_mode the key is stored in
|
||||
* the session data and an identifier is returned using a status
|
||||
* line. */
|
||||
int
|
||||
agent_genkey (ctrl_t ctrl, const char *cache_nonce, time_t timestamp,
|
||||
const char *keyparam, size_t keyparamlen, int no_protection,
|
||||
const char *override_passphrase, int preset, membuf_t *outbuf)
|
||||
agent_genkey (ctrl_t ctrl, unsigned int flags,
|
||||
const char *cache_nonce, time_t timestamp,
|
||||
const char *keyparam, size_t keyparamlen,
|
||||
const char *override_passphrase, membuf_t *outbuf)
|
||||
{
|
||||
gcry_sexp_t s_keyparam, s_key, s_private, s_public;
|
||||
char *passphrase_buffer = NULL;
|
||||
@ -486,7 +550,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, time_t timestamp,
|
||||
/* Get the passphrase now, cause key generation may take a while. */
|
||||
if (override_passphrase)
|
||||
passphrase = override_passphrase;
|
||||
else if (no_protection || !cache_nonce)
|
||||
else if ((flags & GENKEY_FLAG_NO_PROTECTION) || !cache_nonce)
|
||||
passphrase = NULL;
|
||||
else
|
||||
{
|
||||
@ -494,8 +558,8 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, time_t timestamp,
|
||||
passphrase = passphrase_buffer;
|
||||
}
|
||||
|
||||
if (passphrase || no_protection)
|
||||
;
|
||||
if (passphrase || (flags & GENKEY_FLAG_NO_PROTECTION))
|
||||
; /* No need to ask for a passphrase. */
|
||||
else
|
||||
{
|
||||
rc = agent_ask_new_passphrase (ctrl,
|
||||
@ -540,11 +604,14 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, time_t timestamp,
|
||||
gcry_sexp_release (s_key); s_key = NULL;
|
||||
|
||||
/* store the secret key */
|
||||
if (DBG_CRYPTO)
|
||||
log_debug ("storing private key\n");
|
||||
rc = store_key (s_private, passphrase, 0, ctrl->s2k_count, timestamp);
|
||||
if (!rc)
|
||||
if (opt.verbose)
|
||||
log_info ("storing %sprivate key\n",
|
||||
ctrl->ephemeral_mode?"ephemeral ":"");
|
||||
rc = store_key (ctrl, s_private, passphrase, 0, ctrl->s2k_count, timestamp);
|
||||
if (!rc && !ctrl->ephemeral_mode)
|
||||
{
|
||||
/* FIXME: or does it make sense to also cache passphrases in
|
||||
* ephemeral mode using a dedicated cache? */
|
||||
if (!cache_nonce)
|
||||
{
|
||||
char tmpbuf[12];
|
||||
@ -552,18 +619,20 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, time_t timestamp,
|
||||
cache_nonce = bin2hex (tmpbuf, 12, NULL);
|
||||
}
|
||||
if (cache_nonce
|
||||
&& !no_protection
|
||||
&& !(flags & GENKEY_FLAG_NO_PROTECTION)
|
||||
&& !agent_put_cache (ctrl, cache_nonce, CACHE_MODE_NONCE,
|
||||
passphrase, ctrl->cache_ttl_opt_preset))
|
||||
agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
|
||||
if (preset && !no_protection)
|
||||
if ((flags & GENKEY_FLAG_PRESET)
|
||||
&& !(flags & GENKEY_FLAG_NO_PROTECTION))
|
||||
{
|
||||
unsigned char grip[20];
|
||||
char hexgrip[40+1];
|
||||
if (gcry_pk_get_keygrip (s_private, grip))
|
||||
{
|
||||
bin2hex(grip, 20, hexgrip);
|
||||
rc = agent_put_cache (ctrl, hexgrip, CACHE_MODE_ANY, passphrase,
|
||||
rc = agent_put_cache (ctrl, hexgrip,
|
||||
CACHE_MODE_ANY, passphrase,
|
||||
ctrl->cache_ttl_opt_preset);
|
||||
}
|
||||
}
|
||||
@ -615,7 +684,8 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
|
||||
if (passphrase_addr && *passphrase_addr)
|
||||
{
|
||||
/* Take an empty string as request not to protect the key. */
|
||||
err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1,
|
||||
err = store_key (ctrl, s_skey,
|
||||
**passphrase_addr? *passphrase_addr:NULL, 1,
|
||||
ctrl->s2k_count, 0);
|
||||
}
|
||||
else
|
||||
@ -631,7 +701,7 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
|
||||
L_("Please enter the new passphrase"),
|
||||
&pass);
|
||||
if (!err)
|
||||
err = store_key (s_skey, pass, 1, ctrl->s2k_count, 0);
|
||||
err = store_key (ctrl, s_skey, pass, 1, ctrl->s2k_count, 0);
|
||||
if (!err && passphrase_addr)
|
||||
*passphrase_addr = pass;
|
||||
else
|
||||
|
@ -364,7 +364,7 @@ static int putty_support;
|
||||
|
||||
/* Path to the pipe, which handles requests from Win32-OpenSSH. */
|
||||
static const char *win32_openssh_support;
|
||||
#define W32_DEFAILT_AGENT_PIPE_NAME "\\\\.\\pipe\\openssh-ssh-agent"
|
||||
#define W32_DEFAULT_AGENT_PIPE_NAME "\\\\.\\pipe\\openssh-ssh-agent"
|
||||
#endif /*HAVE_W32_SYSTEM*/
|
||||
|
||||
/* The list of open file descriptors at startup. Note that this list
|
||||
@ -1307,7 +1307,7 @@ main (int argc, char **argv)
|
||||
if (pargs.r_type)
|
||||
win32_openssh_support = pargs.r.ret_str;
|
||||
else
|
||||
win32_openssh_support = W32_DEFAILT_AGENT_PIPE_NAME;
|
||||
win32_openssh_support = W32_DEFAULT_AGENT_PIPE_NAME;
|
||||
# endif
|
||||
break;
|
||||
|
||||
@ -2002,6 +2002,7 @@ agent_deinit_default_ctrl (ctrl_t ctrl)
|
||||
{
|
||||
unregister_progress_cb ();
|
||||
session_env_release (ctrl->session_env);
|
||||
clear_ephemeral_keys (ctrl);
|
||||
|
||||
xfree (ctrl->digest.data);
|
||||
ctrl->digest.data = NULL;
|
||||
|
@ -155,6 +155,16 @@ This field is for card key. If given and the value is "yes"
|
||||
dialog window when card is not available. When the value is "no", a
|
||||
card operation is refused with GPG_ERR_UNUSABLE_SECKEY error.
|
||||
|
||||
*** Backup-info
|
||||
This gives information for a backup of the key. The follwoing fields
|
||||
are space delimited:
|
||||
|
||||
- Hexified keygrip (uppercase) to make it easy to identify the
|
||||
filename. When restoring software should make sure that the keygrip
|
||||
matches the one derived from the "Key" field.
|
||||
- Backup time in as ISO string.
|
||||
- Name of the backup software.
|
||||
- Arbitrary information.
|
||||
|
||||
* Private Key Format
|
||||
** Unprotected Private Key Format
|
||||
|
@ -397,7 +397,7 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
|
||||
for (p=item->hexgrip, i=0; i < 20; p += 2, i++)
|
||||
grip[i] = xtoi_2 (p);
|
||||
|
||||
if (!force && !agent_key_available (grip))
|
||||
if (!force && !agent_key_available (ctrl, grip))
|
||||
continue; /* The key is already available. */
|
||||
|
||||
/* Unknown key - store it. */
|
||||
@ -408,12 +408,14 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!ctrl->ephemeral_mode)
|
||||
{
|
||||
char *dispserialno;
|
||||
|
||||
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno,
|
||||
item->hexgrip);
|
||||
rc = agent_write_shadow_key (grip, serialno, item->id, pubkey, force,
|
||||
rc = agent_write_shadow_key (ctrl,
|
||||
grip, serialno, item->id, pubkey, force,
|
||||
dispserialno);
|
||||
xfree (dispserialno);
|
||||
}
|
||||
|
@ -371,13 +371,14 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (keyref)
|
||||
if (keyref && !ctrl->ephemeral_mode)
|
||||
{
|
||||
char *dispserialno;
|
||||
|
||||
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno,
|
||||
hexgrip);
|
||||
agent_write_shadow_key (ctrl->keygrip, serialno, keyref, pkbuf,
|
||||
agent_write_shadow_key (ctrl,
|
||||
ctrl->keygrip, serialno, keyref, pkbuf,
|
||||
0, dispserialno);
|
||||
xfree (dispserialno);
|
||||
}
|
||||
|
@ -755,8 +755,9 @@ release_passphrase (char *pw)
|
||||
|
||||
/* Stub function. */
|
||||
int
|
||||
agent_key_available (const unsigned char *grip)
|
||||
agent_key_available (ctrl_t ctrl, const unsigned char *grip)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)grip;
|
||||
return -1; /* Not available. */
|
||||
}
|
||||
@ -814,7 +815,7 @@ agent_askpin (ctrl_t ctrl,
|
||||
/* Replacement for the function in findkey.c. Here we write the key
|
||||
* to stdout. */
|
||||
gpg_error_t
|
||||
agent_write_private_key (const unsigned char *grip,
|
||||
agent_write_private_key (ctrl_t ctrl, const unsigned char *grip,
|
||||
const void *buffer, size_t length, int force,
|
||||
const char *serialno, const char *keyref,
|
||||
const char *dispserialno, time_t timestamp)
|
||||
@ -822,6 +823,7 @@ agent_write_private_key (const unsigned char *grip,
|
||||
char hexgrip[40+4+1];
|
||||
char *p;
|
||||
|
||||
(void)ctrl;
|
||||
(void)force;
|
||||
(void)serialno;
|
||||
(void)keyref;
|
||||
|
@ -94,16 +94,15 @@
|
||||
# We need to know our own name.
|
||||
SPEEDO_MK := $(realpath $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
.PHONY : help native native-gui w32-installer w32-source w32-wixlib
|
||||
.PHONY : git-native git-native-gui git-w32-installer git-w32-source
|
||||
.PHONY : this-native this-native-gui this-w32-installer this-w32-source
|
||||
.PHONY : help native w32-installer w32-source w32-wixlib
|
||||
.PHONY : git-native git-w32-installer git-w32-source
|
||||
.PHONY : this-native this-w32-installer this-w32-source
|
||||
|
||||
help:
|
||||
@echo 'usage: make -f speedo.mk TARGET'
|
||||
@echo ' with TARGET being one of:'
|
||||
@echo ' help This help'
|
||||
@echo ' native Native build of the GnuPG core'
|
||||
@echo ' native-gui Ditto but with pinentry and GPA'
|
||||
@echo ' w32-installer Build a Windows installer'
|
||||
@echo ' w32-source Pack a source archive'
|
||||
@echo ' w32-release Build a Windows release'
|
||||
@ -114,7 +113,7 @@ help:
|
||||
@echo 'Prepend TARGET with "git-" to build from GIT repos.'
|
||||
@echo 'Prepend TARGET with "this-" to build from the source tarball.'
|
||||
@echo 'Use STATIC=1 to build with statically linked libraries.'
|
||||
@echo 'Use SELFCHECK=0 for a non-released version.'
|
||||
@echo 'Use SELFCHECK=1 for additional check of the gnupg version.'
|
||||
@echo 'Use CUSTOM_SWDB=1 for an already downloaded swdb.lst.'
|
||||
@echo 'Use WIXPREFIX to provide the WIX binaries for the MSI package.'
|
||||
@echo ' Using WIX also requires wine with installed wine mono.'
|
||||
@ -148,66 +147,52 @@ help-wixlib:
|
||||
SPEEDOMAKE := $(MAKE) -f $(SPEEDO_MK) UPD_SWDB=1
|
||||
|
||||
native: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=release WITH_GUI=0 all
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=release all
|
||||
|
||||
git-native: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=git WITH_GUI=0 all
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=git all
|
||||
|
||||
this-native: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=this WITH_GUI=0 all
|
||||
|
||||
native-gui: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=release WITH_GUI=1 all
|
||||
|
||||
git-native-gui: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=git WITH_GUI=1 all
|
||||
|
||||
this-native-gui: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=this WITH_GUI=1 all
|
||||
$(SPEEDOMAKE) TARGETOS=native WHAT=this all
|
||||
|
||||
w32-installer: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release WITH_GUI=0 installer
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release installer
|
||||
|
||||
git-w32-installer: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=git WITH_GUI=0 installer
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=git installer
|
||||
|
||||
this-w32-installer: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=this WITH_GUI=0 \
|
||||
CUSTOM_SWDB=1 installer
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=this CUSTOM_SWDB=1 installer
|
||||
w32-wixlib: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release WITH_GUI=0 wixlib
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release wixlib
|
||||
|
||||
git-w32-wixlib: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=git WITH_GUI=0 wixlib
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=git wixlib
|
||||
|
||||
this-w32-wixlib: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=this WITH_GUI=0 \
|
||||
CUSTOM_SWDB=1 wixlib
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=this CUSTOM_SWDB=1 wixlib
|
||||
|
||||
w32-source: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release WITH_GUI=0 dist-source
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release dist-source
|
||||
|
||||
git-w32-source: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=git WITH_GUI=0 dist-source
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=git dist-source
|
||||
|
||||
this-w32-source: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=this WITH_GUI=0 \
|
||||
CUSTOM_SWDB=1 dist-source
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=this CUSTOM_SWDB=1 dist-source
|
||||
|
||||
w32-release: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release WITH_GUI=0 SELFCHECK=0 \
|
||||
installer-from-source
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release installer-from-source
|
||||
|
||||
w32-msi-release: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release WITH_GUI=0 SELFCHECK=0 \
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release \
|
||||
WITH_WIXLIB=1 installer-from-source
|
||||
|
||||
w32-sign-installer: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release WITH_GUI=0 SELFCHECK=0 \
|
||||
sign-installer
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release sign-installer
|
||||
|
||||
w32-release-offline: check-tools
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release WITH_GUI=0 SELFCHECK=0 \
|
||||
$(SPEEDOMAKE) TARGETOS=w32 WHAT=release \
|
||||
CUSTOM_SWDB=1 pkgrep=${HOME}/b pkg10rep=${HOME}/b \
|
||||
installer-from-source
|
||||
|
||||
@ -220,17 +205,14 @@ WHAT=git
|
||||
# Set target to "native" or "w32"
|
||||
TARGETOS=
|
||||
|
||||
# Set to 1 to build the GUI tools
|
||||
WITH_GUI=0
|
||||
|
||||
# Set to 1 to use a pre-installed swdb.lst instead of the online version.
|
||||
CUSTOM_SWDB=0
|
||||
|
||||
# Set to 1 to really download the swdb.
|
||||
UPD_SWDB=0
|
||||
|
||||
# Set to 0 to skip the GnuPG version self-check
|
||||
SELFCHECK=1
|
||||
# Set to 1 to run an additional GnuPG version check
|
||||
SELFCHECK=0
|
||||
|
||||
# Set to 1 to build with statically linked libraries.
|
||||
STATIC=0
|
||||
@ -240,7 +222,7 @@ STATIC=0
|
||||
TARBALLS=$(shell pwd)/../tarballs
|
||||
|
||||
# Number of parallel make jobs for each package
|
||||
MAKE_J=3
|
||||
MAKE_J=6
|
||||
|
||||
# Name to use for the w32 installer and sources
|
||||
INST_NAME=gnupg-w32
|
||||
@ -251,6 +233,9 @@ INSTALL_PREFIX=none
|
||||
# Set this to the location of wixtools
|
||||
WIXPREFIX=$(shell readlink -f ~/w32root/wixtools)
|
||||
|
||||
# If patchelf(1) is not availale disable the command.
|
||||
PATCHELF := $(shell patchelf --version 2>/dev/null >/dev/null || echo "echo please run: ")patchelf
|
||||
|
||||
# Read signing information from ~/.gnupg-autogen.rc
|
||||
define READ_AUTOGEN_template
|
||||
$(1) = $$(shell grep '^$(1)=' $$$$HOME/.gnupg-autogen.rc|cut -d= -f2)
|
||||
@ -319,60 +304,16 @@ w32src := $(topsrc)/build-aux/speedo/w32
|
||||
# Fixme: Do we need to build pkg-config for cross-building?
|
||||
|
||||
speedo_spkgs = \
|
||||
libgpg-error npth libgcrypt
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
speedo_spkgs += \
|
||||
zlib bzip2 sqlite
|
||||
ifeq ($(WITH_GUI),1)
|
||||
speedo_spkgs += gettext libiconv
|
||||
endif
|
||||
endif
|
||||
|
||||
speedo_spkgs += \
|
||||
libassuan libksba
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
speedo_spkgs += \
|
||||
ntbtls
|
||||
endif
|
||||
|
||||
speedo_spkgs += \
|
||||
gnupg
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
ifeq ($(WITH_GUI),1)
|
||||
speedo_spkgs += \
|
||||
libffi glib pkg-config
|
||||
endif
|
||||
endif
|
||||
libgpg-error npth libgcrypt \
|
||||
zlib bzip2 sqlite \
|
||||
libassuan libksba ntbtls gnupg
|
||||
|
||||
ifeq ($(STATIC),0)
|
||||
speedo_spkgs += \
|
||||
gpgme
|
||||
speedo_spkgs += gpgme
|
||||
endif
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
ifeq ($(WITH_GUI),1)
|
||||
speedo_spkgs += \
|
||||
libpng \
|
||||
gdk-pixbuf atk pixman cairo pango gtk+
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
|
||||
speedo_spkgs += pinentry
|
||||
ifeq ($(WITH_GUI),1)
|
||||
speedo_spkgs += gpa gpgex
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
ifeq ($(WITH_GUI),1)
|
||||
speedo_spkgs += pinentry gpa
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
||||
@ -383,15 +324,12 @@ endif
|
||||
# only used for gpgex and thus we need to build them only if we want
|
||||
# a full installer.
|
||||
speedo_w64_spkgs =
|
||||
ifeq ($(WITH_GUI),1)
|
||||
speedo_w64_spkgs += libgpg-error libiconv gettext libassuan gpgex
|
||||
endif
|
||||
|
||||
# Packages which use the gnupg autogen.sh build style
|
||||
speedo_gnupg_style = \
|
||||
libgpg-error npth libgcrypt \
|
||||
libassuan libksba ntbtls gnupg gpgme \
|
||||
pinentry gpa gpgex
|
||||
pinentry
|
||||
|
||||
# Packages which use only make and no build directory
|
||||
speedo_make_only_style = \
|
||||
@ -451,14 +389,6 @@ pinentry_ver := $(shell awk '$$1=="pinentry_ver" {print $$2}' swdb.lst)
|
||||
pinentry_sha1 := $(shell awk '$$1=="pinentry_sha1" {print $$2}' swdb.lst)
|
||||
pinentry_sha2 := $(shell awk '$$1=="pinentry_sha2" {print $$2}' swdb.lst)
|
||||
|
||||
gpa_ver := $(shell awk '$$1=="gpa_ver" {print $$2}' swdb.lst)
|
||||
gpa_sha1 := $(shell awk '$$1=="gpa_sha1" {print $$2}' swdb.lst)
|
||||
gpa_sha2 := $(shell awk '$$1=="gpa_sha2" {print $$2}' swdb.lst)
|
||||
|
||||
gpgex_ver := $(shell awk '$$1=="gpgex_ver" {print $$2}' swdb.lst)
|
||||
gpgex_sha1 := $(shell awk '$$1=="gpgex_sha1" {print $$2}' swdb.lst)
|
||||
gpgex_sha2 := $(shell awk '$$1=="gpgex_sha2" {print $$2}' swdb.lst)
|
||||
|
||||
zlib_ver := $(shell awk '$$1=="zlib_ver" {print $$2}' swdb.lst)
|
||||
zlib_sha1 := $(shell awk '$$1=="zlib_sha1_gz" {print $$2}' swdb.lst)
|
||||
zlib_sha2 := $(shell awk '$$1=="zlib_sha2_gz" {print $$2}' swdb.lst)
|
||||
@ -474,7 +404,7 @@ sqlite_sha2 := $(shell awk '$$1=="sqlite_sha2_gz" {print $$2}' swdb.lst)
|
||||
|
||||
$(info Information from the version database)
|
||||
$(info GnuPG ..........: $(gnupg_ver) (building $(gnupg_ver_this)))
|
||||
$(info Libgpg-error ...: $(libgpg_error_ver))
|
||||
$(info GpgRT ..........: $(libgpg_error_ver))
|
||||
$(info Npth ...........: $(npth_ver))
|
||||
$(info Libgcrypt ......: $(libgcrypt_ver))
|
||||
$(info Libassuan ......: $(libassuan_ver))
|
||||
@ -485,23 +415,13 @@ $(info SQLite .........: $(sqlite_ver))
|
||||
$(info NtbTLS .. ......: $(ntbtls_ver))
|
||||
$(info GPGME ..........: $(gpgme_ver))
|
||||
$(info Pinentry .......: $(pinentry_ver))
|
||||
$(info GPA ............: $(gpa_ver))
|
||||
$(info GpgEX.... ......: $(gpgex_ver))
|
||||
endif
|
||||
|
||||
# Version number for external packages
|
||||
pkg_config_ver = 0.23
|
||||
libiconv_ver = 1.14
|
||||
gettext_ver = 0.18.2.1
|
||||
libffi_ver = 3.0.13
|
||||
glib_ver = 2.34.3
|
||||
libpng_ver = 1.4.12
|
||||
gdk_pixbuf_ver = 2.26.5
|
||||
atk_ver = 1.32.0
|
||||
pango_ver = 1.29.4
|
||||
pixman_ver = 0.32.4
|
||||
cairo_ver = 1.12.16
|
||||
gtk__ver = 2.24.17
|
||||
|
||||
|
||||
# The GIT repository. Using a local repo is much faster.
|
||||
#gitrep = git://git.gnupg.org
|
||||
@ -552,10 +472,6 @@ else ifeq ($(WHAT),git)
|
||||
speedo_pkg_gpgme_gitref = master
|
||||
speedo_pkg_pinentry_git = $(gitrep)/pinentry
|
||||
speedo_pkg_pinentry_gitref = master
|
||||
speedo_pkg_gpa_git = $(gitrep)/gpa
|
||||
speedo_pkg_gpa_gitref = master
|
||||
speedo_pkg_gpgex_git = $(gitrep)/gpgex
|
||||
speedo_pkg_gpgex_gitref = master
|
||||
else ifeq ($(WHAT),release)
|
||||
speedo_pkg_libgpg_error_tar = \
|
||||
$(pkgrep)/libgpg-error/libgpg-error-$(libgpg_error_ver).tar.bz2
|
||||
@ -573,10 +489,6 @@ else ifeq ($(WHAT),release)
|
||||
$(pkgrep)/gpgme/gpgme-$(gpgme_ver).tar.bz2
|
||||
speedo_pkg_pinentry_tar = \
|
||||
$(pkgrep)/pinentry/pinentry-$(pinentry_ver).tar.bz2
|
||||
speedo_pkg_gpa_tar = \
|
||||
$(pkgrep)/gpa/gpa-$(gpa_ver).tar.bz2
|
||||
speedo_pkg_gpgex_tar = \
|
||||
$(pkg10rep)/gpgex/gpgex-$(gpgex_ver).tar.bz2
|
||||
else
|
||||
$(error invalid value for WHAT (use on of: git release this))
|
||||
endif
|
||||
@ -587,15 +499,6 @@ speedo_pkg_bzip2_tar = $(pkgrep)/bzip2/bzip2-$(bzip2_ver).tar.gz
|
||||
speedo_pkg_sqlite_tar = $(pkgrep)/sqlite/sqlite-autoconf-$(sqlite_ver).tar.gz
|
||||
speedo_pkg_libiconv_tar = $(pkg2rep)/libiconv-$(libiconv_ver).tar.gz
|
||||
speedo_pkg_gettext_tar = $(pkg2rep)/gettext-$(gettext_ver).tar.gz
|
||||
speedo_pkg_libffi_tar = $(pkg2rep)/libffi-$(libffi_ver).tar.gz
|
||||
speedo_pkg_glib_tar = $(pkg2rep)/glib-$(glib_ver).tar.xz
|
||||
speedo_pkg_libpng_tar = $(pkg2rep)/libpng-$(libpng_ver).tar.bz2
|
||||
speedo_pkg_gdk_pixbuf_tar = $(pkg2rep)/gdk-pixbuf-$(gdk_pixbuf_ver).tar.xz
|
||||
speedo_pkg_atk_tar = $(pkg2rep)/atk-$(atk_ver).tar.bz2
|
||||
speedo_pkg_pango_tar = $(pkg2rep)/pango-$(pango_ver).tar.bz2
|
||||
speedo_pkg_pixman_tar = $(pkg2rep)/pixman-$(pixman_ver).tar.gz
|
||||
speedo_pkg_cairo_tar = $(pkg2rep)/cairo-$(cairo_ver).tar.xz
|
||||
speedo_pkg_gtk__tar = $(pkg2rep)/gtk+-$(gtk__ver).tar.xz
|
||||
|
||||
|
||||
#
|
||||
@ -638,7 +541,7 @@ speedo_pkg_gnupg_configure = \
|
||||
else
|
||||
speedo_pkg_gnupg_configure = --disable-g13 --enable-wks-tools
|
||||
endif
|
||||
speedo_pkg_gnupg_extracflags = -g
|
||||
speedo_pkg_gnupg_extracflags =
|
||||
|
||||
# Create the version info files only for W32 so that they won't get
|
||||
# installed if for example INSTALL_PREFIX=/usr/local is used.
|
||||
@ -651,25 +554,13 @@ define speedo_pkg_gnupg_post_install
|
||||
endef
|
||||
endif
|
||||
|
||||
# The LDFLAGS is needed for -lintl for glib.
|
||||
ifeq ($(WITH_GUI),1)
|
||||
speedo_pkg_gpgme_configure = \
|
||||
--enable-static --enable-w32-glib \
|
||||
--with-gpg-error-prefix=$(idir) \
|
||||
LDFLAGS=-L$(idir)/lib
|
||||
else
|
||||
# The LDFLAGS was needed for -lintl for glib.
|
||||
speedo_pkg_gpgme_configure = \
|
||||
--disable-static --disable-w32-glib \
|
||||
--with-gpg-error-prefix=$(idir) \
|
||||
LDFLAGS=-L$(idir)/lib
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
speedo_pkg_pinentry_configure = --disable-pinentry-gtk2
|
||||
else
|
||||
speedo_pkg_pinentry_configure = --enable-pinentry-gtk2
|
||||
endif
|
||||
speedo_pkg_pinentry_configure += \
|
||||
--disable-pinentry-qt5 \
|
||||
--disable-pinentry-qt \
|
||||
@ -680,22 +571,6 @@ speedo_pkg_pinentry_configure += \
|
||||
CXXFLAGS=-static-libstdc++
|
||||
|
||||
|
||||
speedo_pkg_gpa_configure = \
|
||||
--with-libiconv-prefix=$(idir) --with-libintl-prefix=$(idir) \
|
||||
--with-gpgme-prefix=$(idir) --with-zlib=$(idir) \
|
||||
--with-libassuan-prefix=$(idir) --with-gpg-error-prefix=$(idir)
|
||||
|
||||
speedo_pkg_gpgex_configure = \
|
||||
--with-gpg-error-prefix=$(idir) \
|
||||
--with-libassuan-prefix=$(idir) \
|
||||
--enable-gpa-only
|
||||
|
||||
speedo_pkg_w64_gpgex_configure = \
|
||||
--with-gpg-error-prefix=$(idir6) \
|
||||
--with-libassuan-prefix=$(idir6) \
|
||||
--enable-gpa-only
|
||||
|
||||
|
||||
#
|
||||
# External packages
|
||||
#
|
||||
@ -759,64 +634,12 @@ speedo_pkg_gettext_extracflags = -O2
|
||||
speedo_pkg_gettext_make_dir = gettext-runtime
|
||||
|
||||
|
||||
speedo_pkg_glib_configure = \
|
||||
--disable-modular-tests \
|
||||
--with-libiconv=gnu \
|
||||
CPPFLAGS=-I$(idir)/include \
|
||||
LDFLAGS=-L$(idir)/lib \
|
||||
CCC=$(host)-g++ \
|
||||
LIBFFI_CFLAGS=-I$(idir)/lib/libffi-$(libffi_ver)/include \
|
||||
LIBFFI_LIBS=\"-L$(idir)/lib -lffi\"
|
||||
ifeq ($(TARGETOS),w32)
|
||||
speedo_pkg_glib_extracflags = -march=i486
|
||||
endif
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
speedo_pkg_libpng_configure = \
|
||||
CPPFLAGS=\"-I$(idir)/include -DPNG_BUILD_DLL\" \
|
||||
LDFLAGS=\"-L$(idir)/lib\" LIBPNG_DEFINES=\"-DPNG_BUILD_DLL\"
|
||||
else
|
||||
speedo_pkg_libpng_configure = \
|
||||
CPPFLAGS=\"-I$(idir)/include\" \
|
||||
LDFLAGS=\"-L$(idir)/lib\"
|
||||
endif
|
||||
|
||||
ifneq ($(TARGETOS),w32)
|
||||
speedo_pkg_gdk_pixbuf_configure = --without-libtiff --without-libjpeg
|
||||
endif
|
||||
|
||||
speedo_pkg_pixman_configure = \
|
||||
CPPFLAGS=-I$(idir)/include \
|
||||
LDFLAGS=-L$(idir)/lib
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
speedo_pkg_cairo_configure = \
|
||||
--disable-qt --disable-ft --disable-fc \
|
||||
--enable-win32 --enable-win32-font \
|
||||
CPPFLAGS=-I$(idir)/include \
|
||||
LDFLAGS=-L$(idir)/lib
|
||||
else
|
||||
speedo_pkg_cairo_configure = \
|
||||
--disable-qt \
|
||||
CPPFLAGS=-I$(idir)/include \
|
||||
LDFLAGS=-L$(idir)/lib
|
||||
endif
|
||||
|
||||
speedo_pkg_pango_configure = \
|
||||
--disable-gtk-doc \
|
||||
CPPFLAGS=-I$(idir)/include \
|
||||
LDFLAGS=-L$(idir)/lib
|
||||
|
||||
speedo_pkg_gtk__configure = \
|
||||
--disable-cups \
|
||||
CPPFLAGS=-I$(idir)/include \
|
||||
LDFLAGS=-L$(idir)/lib
|
||||
|
||||
|
||||
# ---------
|
||||
|
||||
all: all-speedo
|
||||
|
||||
install: install-speedo
|
||||
|
||||
report: report-speedo
|
||||
|
||||
clean: clean-speedo
|
||||
@ -1286,6 +1109,71 @@ clean-pkg-versions:
|
||||
@: >$(bdir)/pkg-versions.txt
|
||||
|
||||
all-speedo: $(stampdir)/stamp-final
|
||||
ifneq ($(TARGETOS),w32)
|
||||
@(set -e;\
|
||||
cd "$(idir)"; \
|
||||
echo "speedo: Making RPATH relative";\
|
||||
for d in bin sbin libexec lib; do \
|
||||
for f in $$(find $$d -type f); do \
|
||||
if file $$f | grep ELF >/dev/null; then \
|
||||
$(PATCHELF) --set-rpath '$$ORIGIN/../lib' $$f; \
|
||||
fi; \
|
||||
done; \
|
||||
done; \
|
||||
echo "sysconfdir = /etc/gnupg" >bin/gpgconf.ctl ;\
|
||||
echo "rootdir = $(idir)" >>bin/gpgconf.ctl ;\
|
||||
echo "speedo: /*" ;\
|
||||
echo "speedo: * Now copy $(idir)/ to the final location and" ;\
|
||||
echo "speedo: * adjust $(idir)/bin/gpgconf.ctl accordingly" ;\
|
||||
echo "speedo: * Or run:" ;\
|
||||
echo "speedo: * make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg24" ;\
|
||||
echo "speedo: * ldconfig -n /usr/local/gnupg24/lib";\
|
||||
echo "speedo: */")
|
||||
endif
|
||||
|
||||
# No dependencies for the install target; instead we test whether
|
||||
# some of the to be installed files are available. This avoids
|
||||
# accidental rebuilds under a wrong account.
|
||||
install-speedo:
|
||||
ifneq ($(TARGETOS),w32)
|
||||
@(set -e; \
|
||||
cd "$(idir)"; \
|
||||
if [ x"$$SYSROOT" = x ]; then \
|
||||
echo "speedo: ERROR: SYSROOT has not been given";\
|
||||
echo "speedo: Set SYSROOT to the desired install directory";\
|
||||
echo "speedo: Example:";\
|
||||
echo "speedo: make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg24";\
|
||||
echo "speedo: ldconfig -n /usr/local/gnupg24/lib";\
|
||||
exit 1;\
|
||||
fi;\
|
||||
if [ ! -d "$$SYSROOT"/bin ]; then if ! mkdir "$$SYSROOT"/bin; then \
|
||||
echo "speedo: error creating target directory";\
|
||||
exit 1;\
|
||||
fi; fi;\
|
||||
if ! touch "$$SYSROOT"/bin/gpgconf.ctl; then \
|
||||
echo "speedo: Error writing $$SYSROOT/bin/gpgconf.ctl";\
|
||||
echo "speedo: Please check the permissions";\
|
||||
exit 1;\
|
||||
fi;\
|
||||
if [ ! -f bin/gpgconf.ctl ]; then \
|
||||
echo "speedo: ERROR: Nothing to install";\
|
||||
echo "speedo: Please run a build first";\
|
||||
echo "speedo: Example:";\
|
||||
echo "speedo: make -f build-aux/speedo.mk native";\
|
||||
exit 1;\
|
||||
fi;\
|
||||
echo "speedo: Installing files to $$SYSROOT";\
|
||||
find . -type f -executable \
|
||||
-exec install -Dm 755 "{}" "$$SYSROOT/{}" \; ;\
|
||||
find . -type f \! -executable \
|
||||
-exec install -Dm 644 "{}" "$$SYSROOT/{}" \; ;\
|
||||
echo "sysconfdir = /etc/gnupg" > "$$SYSROOT"/bin/gpgconf.ctl ;\
|
||||
echo "rootdir = $$SYSROOT" >> "$$SYSROOT"/bin/gpgconf.ctl ;\
|
||||
echo '/*' ;\
|
||||
echo " * Installation to $$SYSROOT done" ;\
|
||||
echo ' */' )
|
||||
endif
|
||||
|
||||
|
||||
report-speedo: $(addprefix report-,$(speedo_build_list))
|
||||
|
||||
@ -1357,9 +1245,6 @@ $(bdir)/inst-options.ini: $(w32src)/inst-options.ini
|
||||
cat $(w32src)/inst-options.ini >$(bdir)/inst-options.ini
|
||||
|
||||
extra_installer_options =
|
||||
ifeq ($(WITH_GUI),1)
|
||||
extra_installer_options += -DWITH_GUI=1
|
||||
endif
|
||||
|
||||
# Note that we sign only when doing the final installer.
|
||||
installer: all w32_insthelpers $(w32src)/inst-options.ini $(bdir)/README.txt
|
||||
@ -1565,4 +1450,4 @@ check-tools: $(stampdir)/stamp-directories
|
||||
# Mark phony targets
|
||||
#
|
||||
.PHONY: all all-speedo report-speedo clean-stamps clean-speedo installer \
|
||||
w32_insthelpers check-tools clean-pkg-versions
|
||||
w32_insthelpers check-tools clean-pkg-versions install-speedo install
|
||||
|
@ -222,6 +222,10 @@ copy_dir_with_fixup (const char *newdir)
|
||||
{
|
||||
char *result = NULL;
|
||||
char *p;
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
char *p0;
|
||||
const char *s;
|
||||
#endif
|
||||
|
||||
if (!*newdir)
|
||||
return NULL;
|
||||
@ -253,6 +257,29 @@ copy_dir_with_fixup (const char *newdir)
|
||||
*p-- = 0;
|
||||
}
|
||||
|
||||
/* Hack to mitigate badly doubled backslashes. */
|
||||
s = result? result : newdir;
|
||||
if (s[0] == '\\' && s[1] == '\\' && s[2] != '\\')
|
||||
{
|
||||
/* UNC (\\Servername\file) or Long UNC (\\?\Servername\file)
|
||||
* Does not seem to be double quoted. */
|
||||
}
|
||||
else if (strstr (s, "\\\\"))
|
||||
{
|
||||
/* Double quotes detected. Fold them into one because that is
|
||||
* what what Windows does. This way we get a unique hash
|
||||
* regardless of the number of doubled backslashes. */
|
||||
if (!result)
|
||||
result = xstrdup (newdir);
|
||||
for (p0=p=result; *p; p++)
|
||||
{
|
||||
*p0++ = *p;
|
||||
while (*p == '\\' && p[1] == '\\')
|
||||
p++;
|
||||
}
|
||||
*p0 = 0;
|
||||
}
|
||||
|
||||
#else /*!HAVE_W32_SYSTEM*/
|
||||
|
||||
if (newdir[strlen (newdir)-1] == '/')
|
||||
|
@ -84,9 +84,10 @@ static struct
|
||||
modules (eg "xim"). */
|
||||
{ "INSIDE_EMACS" }, /* Set by Emacs before running a
|
||||
process. */
|
||||
{ "PINENTRY_USER_DATA", "pinentry-user-data"}
|
||||
{ "PINENTRY_USER_DATA", "pinentry-user-data"},
|
||||
/* Used for communication with
|
||||
non-standard Pinentries. */
|
||||
{ "PINENTRY_GEOM_HINT" } /* Used to pass window information. */
|
||||
};
|
||||
|
||||
|
||||
|
@ -152,6 +152,7 @@ enum
|
||||
STATUS_TRUNCATED,
|
||||
STATUS_MOUNTPOINT,
|
||||
STATUS_BLOCKDEV,
|
||||
STATUS_PLAINDEV, /* The decrypted virtual device. */
|
||||
|
||||
STATUS_PINENTRY_LAUNCHED,
|
||||
|
||||
|
@ -366,7 +366,7 @@ gpg_error_t b64decode (const char *string, const char *title,
|
||||
/*-- Simple replacement functions. */
|
||||
|
||||
/* We use the gnupg_ttyname macro to be safe not to run into conflicts
|
||||
which an extisting but broken ttyname. */
|
||||
with an existing but broken ttyname. */
|
||||
#if !defined(HAVE_TTYNAME) || defined(HAVE_BROKEN_TTYNAME)
|
||||
# define gnupg_ttyname(n) _gnupg_ttyname ((n))
|
||||
/* Systems without ttyname (W32) will merely return NULL. */
|
||||
|
@ -29,4 +29,4 @@ built on @BUILD_HOSTNAME@ at @BUILD_TIMESTAMP@\0"
|
||||
#define W32INFO_PRODUCTVERSION "@VERSION@\0"
|
||||
|
||||
#define W32INFO_LEGALCOPYRIGHT "Copyright \xa9 \
|
||||
2023 g10 Code GmbH\0"
|
||||
2024 g10 Code GmbH\0"
|
||||
|
@ -525,7 +525,7 @@ AH_BOTTOM([
|
||||
#define GNUPG_OPENPGP_REVOC_DIR "openpgp-revocs.d"
|
||||
#define GNUPG_CACHE_DIR "cache.d"
|
||||
|
||||
#define GNUPG_DEF_COPYRIGHT_LINE "Copyright (C) 2023 g10 Code GmbH"
|
||||
#define GNUPG_DEF_COPYRIGHT_LINE "Copyright (C) 2024 g10 Code GmbH"
|
||||
|
||||
/* For some systems (DOS currently), we hardcode the path here. For
|
||||
POSIX systems the values are constructed by the Makefiles, so that
|
||||
|
@ -623,19 +623,30 @@ are touched.
|
||||
|
||||
@anchor{option --enable-ssh-support}
|
||||
@item --enable-ssh-support
|
||||
@itemx --enable-win32-openssh-support
|
||||
@itemx --enable-putty-support
|
||||
@opindex enable-ssh-support
|
||||
@opindex enable-win32-openssh-support
|
||||
@opindex enable-putty-support
|
||||
|
||||
The OpenSSH Agent protocol is always enabled, but @command{gpg-agent}
|
||||
will only set the @code{SSH_AUTH_SOCK} variable if this flag is given.
|
||||
On Unix platforms the OpenSSH Agent protocol is always enabled, but
|
||||
@command{gpg-agent} will only set the @code{SSH_AUTH_SOCK} variable if
|
||||
the option @option{enable-ssh-support} is given. Some Linux
|
||||
distributions use the presence of this option to decide whether the
|
||||
old ssh-agent shall be started.
|
||||
|
||||
On Windows support for the native ssh implementation must be enabled
|
||||
using the the option @option{enable-win32-openssh-support}. For using
|
||||
gpg-agent as a replacement for PuTTY's Pageant, the option
|
||||
@option{enable-putty-support} must be enabled.
|
||||
|
||||
In this mode of operation, the agent does not only implement the
|
||||
gpg-agent protocol, but also the agent protocol used by OpenSSH
|
||||
(through a separate socket). Consequently, it should be possible to use
|
||||
the gpg-agent as a drop-in replacement for the well known ssh-agent.
|
||||
(through a separate socket or via Named Pipes) or the protocol used by
|
||||
PuTTY. Consequently, this allows to use the gpg-agent as a drop-in
|
||||
replacement for the ssh-agent.
|
||||
|
||||
SSH Keys, which are to be used through the agent, need to be added to
|
||||
SSH keys, which are to be used through the agent, need to be added to
|
||||
the gpg-agent initially through the ssh-add utility. When a key is
|
||||
added, ssh-add will ask for the password of the provided key file and
|
||||
send the unprotected key material to the agent; this causes the
|
||||
|
@ -316,6 +316,40 @@ Write a private key object identified by @var{keygrip} to the card
|
||||
under the id @var{keyref}. Option @option{--force} allows overwriting
|
||||
an existing key.
|
||||
|
||||
@item CHECKKEYS [--ondisk] [--delete-clear-copy] [--delete-protected-copy]
|
||||
@opindex checkkeys
|
||||
Print a list of keys noticed on all inserted cards. With
|
||||
@option{--ondisk} only smartcard keys with a copy on disk are listed.
|
||||
With @option{--delete-clear-copy} copies of smartcard keys stored on
|
||||
disk without any protection will be deleted. With
|
||||
@option{--delete-protected-copy} password protected copies of
|
||||
smartcard keys stored on disk will be deleted.
|
||||
|
||||
This command creates missing shadow keys. The delete options print
|
||||
the status of the keys before they are deleted.
|
||||
|
||||
The format of the output is:
|
||||
@table @var
|
||||
@item Serial number
|
||||
A hex-string with the serial number of the card.
|
||||
@item Type
|
||||
This gives the type of the card's application. For example "OpenPGP"
|
||||
or "PIV".
|
||||
@item Keygrip
|
||||
A hex-string identifying a key.
|
||||
@item Keyref
|
||||
The application slot where the key is stored on the card. For example
|
||||
"OpenPGP.1"
|
||||
@item Status
|
||||
The status of the key. The most common value is "shadowed" for a key
|
||||
where only the public key along with the card's serial number is
|
||||
stored on the disk. The value "clear" indicates that a copy of the
|
||||
card's key is stored unprotected on disk. The value "protected"
|
||||
indicated that a copy of the car's key is stored on disk but is
|
||||
protected by a password. The value "error" may also be shown if there
|
||||
was a problem reading information from the card.
|
||||
@end table
|
||||
|
||||
@item YUBIKEY @var{cmd} @var{args}
|
||||
@opindex yubikey
|
||||
Various commands pertaining to Yubikey tokens with @var{cmd} being:
|
||||
|
24
doc/gpg.texi
24
doc/gpg.texi
@ -638,12 +638,11 @@ The @option{--dearmor} command can also be used to dearmor PEM armors.
|
||||
|
||||
@item --unwrap
|
||||
@opindex unwrap
|
||||
This command is similar to @option{--decrypt} with the difference that the
|
||||
output is not the usual plaintext but the original message with the
|
||||
encryption layer removed. Thus the output will be an OpenPGP data
|
||||
structure which often means a signed OpenPGP message. Note that this
|
||||
option may or may not remove a compression layer which is often found
|
||||
beneath the encryption layer.
|
||||
This option modifies the command @option{--decrypt} to output the
|
||||
original message with the encryption layer removed. Thus the output
|
||||
will be an OpenPGP data structure which often means a signed OpenPGP
|
||||
message. Note that this option may or may not remove a compression
|
||||
layer which is often found beneath the encryption layer.
|
||||
|
||||
@item --tofu-policy @{auto|good|unknown|bad|ask@} @var{keys}
|
||||
@opindex tofu-policy
|
||||
@ -2580,6 +2579,10 @@ opposite meaning. The options are:
|
||||
import-clean it suppresses the final clean step after merging the
|
||||
imported key into the existing key.
|
||||
|
||||
@item ignore-attributes
|
||||
Ignore all attribute user IDs (photo IDs) and their signatures while
|
||||
importing a key.
|
||||
|
||||
@item repair-keys
|
||||
After import, fix various problems with the
|
||||
keys. For example, this reorders signatures, and strips duplicate
|
||||
@ -4637,10 +4640,11 @@ in the @option{--edit-key} menu.
|
||||
|
||||
@item Revoker: @var{algo}:@var{fpr} [sensitive]
|
||||
Add a designated revoker to the generated key. Algo is the public key
|
||||
algorithm of the designated revoker (i.e., RSA=1, DSA=17, etc.)
|
||||
@var{fpr} is the fingerprint of the designated revoker. The optional
|
||||
@samp{sensitive} flag marks the designated revoker as sensitive
|
||||
information. Only v4 keys may be designated revokers.
|
||||
algorithm of the designated revoker (i.e. RSA=1, DSA=17, etc.)
|
||||
@var{fpr} is the fingerprint of the designated revoker. @var{fpr} may
|
||||
not contain spaces or colons. The optional @samp{sensitive} flag
|
||||
marks the designated revoker as sensitive information. Only v4 and v5
|
||||
keys may be designated revokers.
|
||||
|
||||
@item Keyserver: @var{string}
|
||||
This is an optional parameter that specifies the preferred keyserver
|
||||
|
@ -387,12 +387,23 @@ daemons. Note that as of now reload and kill have the same effect for
|
||||
Create a directory for sockets below /run/user or /var/run/user. This
|
||||
is command is only required if a non default home directory is used
|
||||
and the /run based sockets shall be used. For the default home
|
||||
directory GnUPG creates a directory on the fly.
|
||||
directory GnuPG creates a directory on the fly.
|
||||
|
||||
@item --remove-socketdir
|
||||
@opindex remove-socketdir
|
||||
Remove a directory created with command @option{--create-socketdir}.
|
||||
|
||||
@item --unlock @var{name}
|
||||
@itemx --lock @var{name}
|
||||
Remove a stale lock file hold for @file{file}. The file is
|
||||
expected in the current GnuPG home directory. This command is usually
|
||||
not required because GnuPG is able to detect and remove stale lock
|
||||
files. Before using the command make sure that the file protected by
|
||||
the lock file is actually not in use. The lock command may be used to
|
||||
lock an accidently removed lock file. Note that the commands have no
|
||||
effect on Windows because the mere existence of a lock file does not
|
||||
mean that the lock is active.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
|
@ -2227,7 +2227,14 @@ keyinfo_status_cb (void *opaque, const char *line)
|
||||
|
||||
|
||||
/* Ask the agent whether a secret key for the given public key is
|
||||
available. Returns 0 if not available. Bigger value is preferred. */
|
||||
* available. Returns 0 if not available. Bigger value is preferred.
|
||||
* Will never return a value less than 0. Defined return values are:
|
||||
* 0 := No key or error
|
||||
* 1 := Key available
|
||||
* 2 := Key available on a smartcard
|
||||
* 3 := Key available and passphrase cached
|
||||
* 4 := Key available on current smartcard
|
||||
*/
|
||||
int
|
||||
agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
|
||||
{
|
||||
@ -2241,11 +2248,11 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
|
||||
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
return 0;
|
||||
|
||||
err = hexkeygrip_from_pk (pk, &hexgrip);
|
||||
if (err)
|
||||
return err;
|
||||
return 0;
|
||||
|
||||
snprintf (line, sizeof line, "KEYINFO %s", hexgrip);
|
||||
xfree (hexgrip);
|
||||
@ -3237,6 +3244,45 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc, int verify,
|
||||
}
|
||||
|
||||
|
||||
/* Enable or disable the ephemeral mode. In ephemeral mode keys are
|
||||
* created,searched and used in a per-session key store and not in the
|
||||
* on-disk file. Set ENABLE to 1 to enable this mode, to 0 to disable
|
||||
* this mode and to -1 to only query the current mode. If R_PREVIOUS
|
||||
* is given the previously used state of the ephemeral mode is stored
|
||||
* at that address. */
|
||||
gpg_error_t
|
||||
agent_set_ephemeral_mode (ctrl_t ctrl, int enable, int *r_previous)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
if (r_previous)
|
||||
{
|
||||
err = assuan_transact (agent_ctx, "GETINFO ephemeral",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (!err)
|
||||
*r_previous = 1;
|
||||
else if (gpg_err_code (err) == GPG_ERR_FALSE)
|
||||
*r_previous = 0;
|
||||
else
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Skip setting if we are only querying or if the mode is already set. */
|
||||
if (enable == -1 || (r_previous && !!*r_previous == !!enable))
|
||||
err = 0;
|
||||
else
|
||||
err = assuan_transact (agent_ctx,
|
||||
enable? "OPTION ephemeral=1" : "OPTION ephemeral=0",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
leave:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Return the version reported by gpg-agent. */
|
||||
gpg_error_t
|
||||
agent_get_version (ctrl_t ctrl, char **r_version)
|
||||
|
@ -247,6 +247,10 @@ gpg_error_t agent_delete_key (ctrl_t ctrl, const char *hexkeygrip,
|
||||
gpg_error_t agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
||||
int verify,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr);
|
||||
|
||||
/* Set or get the ephemeral mode. */
|
||||
gpg_error_t agent_set_ephemeral_mode (ctrl_t ctrl, int enable, int *r_previous);
|
||||
|
||||
/* Get the version reported by gpg-agent. */
|
||||
gpg_error_t agent_get_version (ctrl_t ctrl, char **r_version);
|
||||
|
||||
|
33
g10/getkey.c
33
g10/getkey.c
@ -2009,8 +2009,9 @@ parse_def_secret_key (ctrl_t ctrl)
|
||||
{
|
||||
gpg_error_t err;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
KBNODE kb;
|
||||
KBNODE node;
|
||||
kbnode_t kb;
|
||||
kbnode_t node;
|
||||
int any_revoked, any_expired, any_disabled;
|
||||
|
||||
err = classify_user_id (t->d, &desc, 1);
|
||||
if (err)
|
||||
@ -2053,6 +2054,7 @@ parse_def_secret_key (ctrl_t ctrl)
|
||||
|
||||
merge_selfsigs (ctrl, kb);
|
||||
|
||||
any_revoked = any_expired = any_disabled = 0;
|
||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
node = kb;
|
||||
do
|
||||
@ -2062,6 +2064,7 @@ parse_def_secret_key (ctrl_t ctrl)
|
||||
/* Check if the key is valid. */
|
||||
if (pk->flags.revoked)
|
||||
{
|
||||
any_revoked = 1;
|
||||
if (DBG_LOOKUP)
|
||||
log_debug ("not using %s as default key, %s",
|
||||
keystr_from_pk (pk), "revoked");
|
||||
@ -2069,6 +2072,7 @@ parse_def_secret_key (ctrl_t ctrl)
|
||||
}
|
||||
if (pk->has_expired)
|
||||
{
|
||||
any_expired = 1;
|
||||
if (DBG_LOOKUP)
|
||||
log_debug ("not using %s as default key, %s",
|
||||
keystr_from_pk (pk), "expired");
|
||||
@ -2076,6 +2080,7 @@ parse_def_secret_key (ctrl_t ctrl)
|
||||
}
|
||||
if (pk_is_disabled (pk))
|
||||
{
|
||||
any_disabled = 1;
|
||||
if (DBG_LOOKUP)
|
||||
log_debug ("not using %s as default key, %s",
|
||||
keystr_from_pk (pk), "disabled");
|
||||
@ -2096,9 +2101,22 @@ parse_def_secret_key (ctrl_t ctrl)
|
||||
{
|
||||
if (! warned && ! opt.quiet)
|
||||
{
|
||||
gpg_err_code_t ec;
|
||||
|
||||
/* Try to get a better error than no secret key if we
|
||||
* only know that the public key is not usable. */
|
||||
if (any_revoked)
|
||||
ec = GPG_ERR_CERT_REVOKED;
|
||||
else if (any_expired)
|
||||
ec = GPG_ERR_KEY_EXPIRED;
|
||||
else if (any_disabled)
|
||||
ec = GPG_ERR_KEY_DISABLED;
|
||||
else
|
||||
ec = GPG_ERR_NO_SECKEY;
|
||||
|
||||
log_info (_("Warning: not using '%s' as default key: %s\n"),
|
||||
t->d, gpg_strerror (GPG_ERR_NO_SECKEY));
|
||||
print_reported_error (err, GPG_ERR_NO_SECKEY);
|
||||
t->d, gpg_strerror (ec));
|
||||
print_reported_error (err, ec);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -3772,6 +3790,13 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (secret_key_avail < last_secret_key_avail)
|
||||
{
|
||||
if (DBG_LOOKUP)
|
||||
log_debug ("\tskipping secret key with lower avail\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (secret_key_avail > last_secret_key_avail)
|
||||
{
|
||||
/* Use this key. */
|
||||
|
12
g10/import.c
12
g10/import.c
@ -209,6 +209,9 @@ parse_import_options(char *str,unsigned int *options,int noisy)
|
||||
{"repair-keys", IMPORT_REPAIR_KEYS, NULL,
|
||||
N_("repair keys on import")},
|
||||
|
||||
/* New options. Right now, without description string. */
|
||||
{"ignore-attributes", IMPORT_IGNORE_ATTRIBUTES, NULL, NULL},
|
||||
|
||||
/* Hidden options which are enabled by default and are provided
|
||||
* in case of problems with the respective implementation. */
|
||||
{"collapse-uids", IMPORT_COLLAPSE_UIDS, NULL, NULL},
|
||||
@ -1008,6 +1011,15 @@ read_block( IOBUF a, unsigned int options,
|
||||
init_packet(pkt);
|
||||
continue;
|
||||
}
|
||||
else if ((opt.import_options & IMPORT_IGNORE_ATTRIBUTES)
|
||||
&& (pkt->pkttype == PKT_USER_ID || pkt->pkttype == PKT_ATTRIBUTE)
|
||||
&& pkt->pkt.user_id->attrib_data)
|
||||
{
|
||||
skip_sigs = 1;
|
||||
free_packet (pkt, &parsectx);
|
||||
init_packet (pkt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skip_sigs)
|
||||
{
|
||||
|
@ -746,14 +746,16 @@ keydb_add_resource (const char *url, unsigned int flags)
|
||||
err = gpg_error (GPG_ERR_RESOURCE_LIMIT);
|
||||
else
|
||||
{
|
||||
KEYBOX_HANDLE kbxhd;
|
||||
|
||||
if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY))
|
||||
primary_keydb = token;
|
||||
all_resources[used_resources].type = rt;
|
||||
all_resources[used_resources].u.kb = NULL; /* Not used here */
|
||||
all_resources[used_resources].token = token;
|
||||
|
||||
if (!(flags & KEYDB_RESOURCE_FLAG_READONLY))
|
||||
{
|
||||
KEYBOX_HANDLE kbxhd;
|
||||
|
||||
/* Do a compress run if needed and no other user is
|
||||
* currently using the keybox. */
|
||||
kbxhd = keybox_new_openpgp (token, 0);
|
||||
@ -767,7 +769,7 @@ keydb_add_resource (const char *url, unsigned int flags)
|
||||
|
||||
keybox_release (kbxhd);
|
||||
}
|
||||
|
||||
}
|
||||
used_resources++;
|
||||
}
|
||||
}
|
||||
|
@ -1905,6 +1905,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
||||
PACKET *pkt;
|
||||
IOBUF a;
|
||||
struct parse_packet_ctx_s parsectx;
|
||||
int lastmode;
|
||||
|
||||
if (!*arg_string)
|
||||
{
|
||||
@ -1959,9 +1960,16 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
||||
xfree (fname);
|
||||
node = new_kbnode (pkt);
|
||||
|
||||
err = agent_set_ephemeral_mode (ctrl, 1, &lastmode);
|
||||
if (err)
|
||||
log_error ("error switching to ephemeral mode: %s\n",
|
||||
gpg_strerror (err));
|
||||
else
|
||||
{
|
||||
/* Transfer it to gpg-agent which handles secret keys. */
|
||||
err = transfer_secret_keys (ctrl, NULL, node, 1, 1, 0);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
/* Treat the pkt as a public key. */
|
||||
pkt->pkttype = PKT_PUBLIC_KEY;
|
||||
|
||||
@ -1971,6 +1979,10 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
||||
redisplay = 1;
|
||||
sec_shadowing = 1;
|
||||
}
|
||||
}
|
||||
if (!lastmode && agent_set_ephemeral_mode (ctrl, 0, NULL))
|
||||
log_error ("error clearing the ephemeral mode\n");
|
||||
}
|
||||
release_kbnode (node);
|
||||
}
|
||||
break;
|
||||
@ -3212,7 +3224,7 @@ keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
|
||||
/* We require a fingerprint because only this uniquely identifies a
|
||||
* key and may thus be used to select a key for unattended subkey
|
||||
* creation. */
|
||||
if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
|
||||
if ((err=find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd)))
|
||||
goto leave;
|
||||
|
||||
if (fix_keyblock (ctrl, &keyblock))
|
||||
@ -3224,6 +3236,7 @@ keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
|
||||
if (!opt.verbose)
|
||||
show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
|
||||
log_error ("%s%s", _("Key is revoked."), "\n");
|
||||
err = gpg_error (GPG_ERR_CERT_REVOKED);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -3247,6 +3260,8 @@ keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
|
||||
log_info (_("Key not changed so no update needed.\n"));
|
||||
|
||||
leave:
|
||||
if (err)
|
||||
write_status_error ("keyedit.addkey", err);
|
||||
release_kbnode (keyblock);
|
||||
keydb_release (kdbhd);
|
||||
}
|
||||
@ -3274,7 +3289,7 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
|
||||
/* We require a fingerprint because only this uniquely identifies a
|
||||
* key and may thus be used to select a key for unattended adsk
|
||||
* adding. */
|
||||
if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
|
||||
if ((err = find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd)))
|
||||
goto leave;
|
||||
|
||||
if (fix_keyblock (ctrl, &keyblock))
|
||||
@ -3286,6 +3301,7 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
|
||||
if (!opt.verbose)
|
||||
show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
|
||||
log_error ("%s%s", _("Key is revoked."), "\n");
|
||||
err = gpg_error (GPG_ERR_CERT_REVOKED);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -3310,6 +3326,8 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
|
||||
}
|
||||
|
||||
leave:
|
||||
if (err)
|
||||
write_status_error ("keyedit.addadsk", err);
|
||||
release_kbnode (keyblock);
|
||||
keydb_release (kdbhd);
|
||||
}
|
||||
@ -3318,7 +3336,7 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
|
||||
/* Unattended expiration setting function for the main key. If
|
||||
* SUBKEYFPRS is not NULL and SUBKEYSFPRS[0] is neither NULL, it is
|
||||
* expected to be an array of fingerprints for subkeys to change. It
|
||||
* may also be an array which just one item "*" to indicate that all
|
||||
* may also be an array with only the item "*" to indicate that all
|
||||
* keys shall be set to that expiration date.
|
||||
*/
|
||||
void
|
||||
|
263
g10/keygen.c
263
g10/keygen.c
@ -131,6 +131,18 @@ struct output_control_s
|
||||
};
|
||||
|
||||
|
||||
/* An object to help communicating with the actual key generation
|
||||
* code. */
|
||||
struct common_gen_cb_parm_s
|
||||
{
|
||||
/* This variable set to the result of agent_genkey. The callback
|
||||
* may take a copy of this so that the result can be used after we
|
||||
* are back from the deep key generation call stack. */
|
||||
gcry_sexp_t genkey_result;
|
||||
};
|
||||
typedef struct common_gen_cb_parm_s *common_gen_cb_parm_t;
|
||||
|
||||
|
||||
/* FIXME: These globals vars are ugly. And using MAX_PREFS even for
|
||||
* aeads is useless, given that we don't expects more than a very few
|
||||
* algorithms. */
|
||||
@ -159,7 +171,7 @@ static void do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
||||
static int write_keyblock (iobuf_t out, kbnode_t node);
|
||||
static gpg_error_t gen_card_key (int keyno, int algo, int is_primary,
|
||||
kbnode_t pub_root, u32 *timestamp,
|
||||
u32 expireval, int keygen_flags);
|
||||
u32 expireval, int *keygen_flags);
|
||||
static unsigned int get_keysize_range (int algo,
|
||||
unsigned int *min, unsigned int *max);
|
||||
|
||||
@ -1266,6 +1278,39 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
|
||||
}
|
||||
|
||||
|
||||
/* Returns true if SEXP specified the curve ED448 or X448. */
|
||||
static int
|
||||
curve_is_448 (gcry_sexp_t sexp)
|
||||
{
|
||||
gcry_sexp_t list, l2;
|
||||
char *curve;
|
||||
int result;
|
||||
|
||||
list = gcry_sexp_find_token (sexp, "public-key", 0);
|
||||
if (!list)
|
||||
return 0; /* Not a public key. */
|
||||
l2 = gcry_sexp_cadr (list);
|
||||
gcry_sexp_release (list);
|
||||
list = l2;
|
||||
if (!list)
|
||||
return 0; /* Bad public key. */
|
||||
|
||||
l2 = gcry_sexp_find_token (list, "curve", 0);
|
||||
gcry_sexp_release (list);
|
||||
if (!l2)
|
||||
return 0; /* No curve parameter. */
|
||||
curve = gcry_sexp_nth_string (l2, 1);
|
||||
gcry_sexp_release (l2);
|
||||
if (!curve)
|
||||
return 0; /* Bad curve parameter. */
|
||||
result = (!ascii_strcasecmp (curve, "X448")
|
||||
|| !ascii_strcasecmp (curve, "Ed448")
|
||||
|| !ascii_strcasecmp (curve, "cv448"));
|
||||
xfree (curve);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, int algo)
|
||||
{
|
||||
@ -1404,7 +1449,7 @@ static int
|
||||
do_create_from_keygrip (ctrl_t ctrl, int algo,
|
||||
const char *hexkeygrip, int cardkey,
|
||||
kbnode_t pub_root, u32 timestamp, u32 expireval,
|
||||
int is_subkey, int keygen_flags)
|
||||
int is_subkey, int *keygen_flags)
|
||||
{
|
||||
int err;
|
||||
PACKET *pkt;
|
||||
@ -1448,6 +1493,10 @@ do_create_from_keygrip (ctrl_t ctrl, int algo,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* For X448 we force the use of v5 packets. */
|
||||
if (curve_is_448 (s_key))
|
||||
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
|
||||
|
||||
/* Build a public key packet. */
|
||||
pk = xtrycalloc (1, sizeof *pk);
|
||||
if (!pk)
|
||||
@ -1458,7 +1507,7 @@ do_create_from_keygrip (ctrl_t ctrl, int algo,
|
||||
}
|
||||
|
||||
pk->timestamp = timestamp;
|
||||
pk->version = (keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
|
||||
pk->version = (*keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
|
||||
if (expireval)
|
||||
pk->expiredate = pk->timestamp + expireval;
|
||||
pk->pubkey_algo = algo;
|
||||
@ -1494,12 +1543,17 @@ do_create_from_keygrip (ctrl_t ctrl, int algo,
|
||||
}
|
||||
|
||||
|
||||
/* Common code for the key generation function gen_xxx. */
|
||||
/* Common code for the key generation function gen_xxx. The optinal
|
||||
* (COMMON_GEN_CB,COMMON_GEN_CB_PARM) can be used as communication
|
||||
* object.
|
||||
*/
|
||||
static int
|
||||
common_gen (const char *keyparms, int algo, const char *algoelem,
|
||||
kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey,
|
||||
int keygen_flags, const char *passphrase,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr)
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr,
|
||||
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
|
||||
common_gen_cb_parm_t common_gen_cb_parm)
|
||||
{
|
||||
int err;
|
||||
PACKET *pkt;
|
||||
@ -1516,6 +1570,18 @@ common_gen (const char *keyparms, int algo, const char *algoelem,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (common_gen_cb && common_gen_cb_parm)
|
||||
{
|
||||
common_gen_cb_parm->genkey_result = s_key;
|
||||
err = common_gen_cb (common_gen_cb_parm);
|
||||
common_gen_cb_parm->genkey_result = NULL;
|
||||
if (err)
|
||||
{
|
||||
gcry_sexp_release (s_key);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
pk = xtrycalloc (1, sizeof *pk);
|
||||
if (!pk)
|
||||
{
|
||||
@ -1568,7 +1634,9 @@ static int
|
||||
gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
|
||||
u32 timestamp, u32 expireval, int is_subkey,
|
||||
int keygen_flags, const char *passphrase,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr)
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr,
|
||||
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
|
||||
common_gen_cb_parm_t common_gen_cb_parm)
|
||||
{
|
||||
int err;
|
||||
char *keyparms;
|
||||
@ -1610,7 +1678,8 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
|
||||
err = common_gen (keyparms, algo, "pgy",
|
||||
pub_root, timestamp, expireval, is_subkey,
|
||||
keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr);
|
||||
cache_nonce_addr, passwd_nonce_addr,
|
||||
common_gen_cb, common_gen_cb_parm);
|
||||
xfree (keyparms);
|
||||
}
|
||||
|
||||
@ -1625,7 +1694,9 @@ static gpg_error_t
|
||||
gen_dsa (unsigned int nbits, KBNODE pub_root,
|
||||
u32 timestamp, u32 expireval, int is_subkey,
|
||||
int keygen_flags, const char *passphrase,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr)
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr,
|
||||
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
|
||||
common_gen_cb_parm_t common_gen_cb_parm)
|
||||
{
|
||||
int err;
|
||||
unsigned int qbits;
|
||||
@ -1699,7 +1770,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
|
||||
err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy",
|
||||
pub_root, timestamp, expireval, is_subkey,
|
||||
keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr);
|
||||
cache_nonce_addr, passwd_nonce_addr,
|
||||
common_gen_cb, common_gen_cb_parm);
|
||||
xfree (keyparms);
|
||||
}
|
||||
|
||||
@ -1709,13 +1781,17 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
|
||||
|
||||
|
||||
/*
|
||||
* Generate an ECC key
|
||||
* Generate an ECC key.
|
||||
* Note that KEYGEN_FLAGS might be updated by this function to
|
||||
* indicate the forced creation of a v5 key.
|
||||
*/
|
||||
static gpg_error_t
|
||||
gen_ecc (int algo, const char *curve, kbnode_t pub_root,
|
||||
u32 timestamp, u32 expireval, int is_subkey,
|
||||
int keygen_flags, const char *passphrase,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr)
|
||||
int *keygen_flags, const char *passphrase,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr,
|
||||
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
|
||||
common_gen_cb_parm_t common_gen_cb_parm)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char *keyparms;
|
||||
@ -1741,40 +1817,52 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
|
||||
/* Note that we use the "comp" flag with EdDSA to request the use of
|
||||
a 0x40 compression prefix octet. */
|
||||
if (algo == PUBKEY_ALGO_EDDSA && !strcmp (curve, "Ed25519"))
|
||||
{
|
||||
keyparms = xtryasprintf
|
||||
("(genkey(ecc(curve %zu:%s)(flags eddsa comp%s)))",
|
||||
strlen (curve), curve,
|
||||
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
" transient-key" : ""));
|
||||
}
|
||||
else if (algo == PUBKEY_ALGO_EDDSA && !strcmp (curve, "Ed448"))
|
||||
{
|
||||
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
|
||||
keyparms = xtryasprintf
|
||||
("(genkey(ecc(curve %zu:%s)(flags comp%s)))",
|
||||
strlen (curve), curve,
|
||||
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
" transient-key" : ""));
|
||||
}
|
||||
else if (algo == PUBKEY_ALGO_ECDH && !strcmp (curve, "Curve25519"))
|
||||
{
|
||||
keyparms = xtryasprintf
|
||||
("(genkey(ecc(curve %zu:%s)(flags djb-tweak comp%s)))",
|
||||
strlen (curve), curve,
|
||||
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
" transient-key" : ""));
|
||||
}
|
||||
else if (algo == PUBKEY_ALGO_ECDH && !strcmp (curve, "X448"))
|
||||
{
|
||||
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
|
||||
keyparms = xtryasprintf
|
||||
("(genkey(ecc(curve %zu:%s)(flags comp%s)))",
|
||||
strlen (curve), curve,
|
||||
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
" transient-key" : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
keyparms = xtryasprintf
|
||||
("(genkey(ecc(curve %zu:%s)(flags nocomp%s)))",
|
||||
strlen (curve), curve,
|
||||
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||
" transient-key" : ""));
|
||||
}
|
||||
|
||||
if (!keyparms)
|
||||
err = gpg_error_from_syserror ();
|
||||
@ -1782,8 +1870,9 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
|
||||
{
|
||||
err = common_gen (keyparms, algo, "",
|
||||
pub_root, timestamp, expireval, is_subkey,
|
||||
keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr);
|
||||
*keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr,
|
||||
common_gen_cb, common_gen_cb_parm);
|
||||
xfree (keyparms);
|
||||
}
|
||||
|
||||
@ -1798,7 +1887,9 @@ static int
|
||||
gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
|
||||
u32 timestamp, u32 expireval, int is_subkey,
|
||||
int keygen_flags, const char *passphrase,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr)
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr,
|
||||
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
|
||||
common_gen_cb_parm_t common_gen_cb_parm)
|
||||
{
|
||||
int err;
|
||||
char *keyparms;
|
||||
@ -1840,7 +1931,8 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
|
||||
err = common_gen (keyparms, algo, "ne",
|
||||
pub_root, timestamp, expireval, is_subkey,
|
||||
keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr);
|
||||
cache_nonce_addr, passwd_nonce_addr,
|
||||
common_gen_cb, common_gen_cb_parm);
|
||||
xfree (keyparms);
|
||||
}
|
||||
|
||||
@ -3200,12 +3292,15 @@ ask_user_id (int mode, int full, KBNODE keyblock)
|
||||
|
||||
|
||||
/* Basic key generation. Here we divert to the actual generation
|
||||
routines based on the requested algorithm. */
|
||||
* routines based on the requested algorithm. KEYGEN_FLAGS might be
|
||||
* updated by this function. */
|
||||
static int
|
||||
do_create (int algo, unsigned int nbits, const char *curve, kbnode_t pub_root,
|
||||
u32 timestamp, u32 expiredate, int is_subkey,
|
||||
int keygen_flags, const char *passphrase,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr)
|
||||
int *keygen_flags, const char *passphrase,
|
||||
char **cache_nonce_addr, char **passwd_nonce_addr,
|
||||
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
|
||||
common_gen_cb_parm_t common_gen_cb_parm)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
@ -3220,22 +3315,26 @@ do_create (int algo, unsigned int nbits, const char *curve, kbnode_t pub_root,
|
||||
|
||||
if (algo == PUBKEY_ALGO_ELGAMAL_E)
|
||||
err = gen_elg (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
|
||||
keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr);
|
||||
*keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr,
|
||||
common_gen_cb, common_gen_cb_parm);
|
||||
else if (algo == PUBKEY_ALGO_DSA)
|
||||
err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey,
|
||||
keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr);
|
||||
*keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr,
|
||||
common_gen_cb, common_gen_cb_parm);
|
||||
else if (algo == PUBKEY_ALGO_ECDSA
|
||||
|| algo == PUBKEY_ALGO_EDDSA
|
||||
|| algo == PUBKEY_ALGO_ECDH)
|
||||
err = gen_ecc (algo, curve, pub_root, timestamp, expiredate, is_subkey,
|
||||
keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr);
|
||||
cache_nonce_addr, passwd_nonce_addr,
|
||||
common_gen_cb, common_gen_cb_parm);
|
||||
else if (algo == PUBKEY_ALGO_RSA)
|
||||
err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
|
||||
keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr);
|
||||
*keygen_flags, passphrase,
|
||||
cache_nonce_addr, passwd_nonce_addr,
|
||||
common_gen_cb, common_gen_cb_parm);
|
||||
else
|
||||
BUG();
|
||||
|
||||
@ -4106,7 +4205,7 @@ parse_revocation_key (const char *fname,
|
||||
|
||||
pn++;
|
||||
|
||||
for(i=0;i<MAX_FINGERPRINT_LEN && *pn;i++,pn+=2)
|
||||
for(i=0;i<MAX_FINGERPRINT_LEN && *pn && !spacep (pn);i++,pn+=2)
|
||||
{
|
||||
int c=hextobyte(pn);
|
||||
if(c==-1)
|
||||
@ -4247,12 +4346,13 @@ proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
||||
if (!err)
|
||||
{
|
||||
/* Default to algo capabilities if subkey-usage is not
|
||||
provided */
|
||||
provided. Take care not to include RENC. */
|
||||
r = xmalloc_clear (sizeof(*r));
|
||||
r->key = pSUBKEYUSAGE;
|
||||
r->u.usage = (is_default
|
||||
? PUBKEY_USAGE_ENC
|
||||
: openpgp_pk_algo_usage (algo));
|
||||
: (openpgp_pk_algo_usage (algo)
|
||||
& ~PUBKEY_USAGE_RENC) );
|
||||
append_to_parameter (para, r);
|
||||
}
|
||||
else if (err == -1)
|
||||
@ -5100,7 +5200,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
|
||||
strcpy (r->u.value, curve);
|
||||
r->next = para;
|
||||
para = r;
|
||||
if (!strcmp (curve, "Ed448"))
|
||||
if (!strcmp (curve, "X448") || !strcmp (curve, "Ed448"))
|
||||
{
|
||||
r = xmalloc_clear (sizeof *r + 20);
|
||||
r->key = pVERSION;
|
||||
@ -5182,7 +5282,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
|
||||
strcpy (r->u.value, curve);
|
||||
r->next = para;
|
||||
para = r;
|
||||
if (!strcmp (curve, "Ed448"))
|
||||
if (!strcmp (curve, "X448") || !strcmp (curve, "Ed448"))
|
||||
{
|
||||
r = xmalloc_clear (sizeof *r + 20);
|
||||
r->key = pVERSION;
|
||||
@ -5613,7 +5713,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
||||
err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip, cardkey,
|
||||
pub_root,
|
||||
keytimestamp,
|
||||
expire, 0, keygen_flags);
|
||||
expire, 0, &keygen_flags);
|
||||
else if (!card)
|
||||
err = do_create (algo,
|
||||
get_parameter_uint( para, pKEYLENGTH ),
|
||||
@ -5621,13 +5721,14 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
||||
pub_root,
|
||||
keytimestamp,
|
||||
expire, 0,
|
||||
keygen_flags,
|
||||
&keygen_flags,
|
||||
get_parameter_passphrase (para),
|
||||
&cache_nonce, NULL);
|
||||
&cache_nonce, NULL,
|
||||
NULL, NULL);
|
||||
else
|
||||
err = gen_card_key (1, algo,
|
||||
1, pub_root, &keytimestamp,
|
||||
expire, keygen_flags);
|
||||
expire, &keygen_flags);
|
||||
|
||||
/* Get the pointer to the generated public key packet. */
|
||||
if (!err)
|
||||
@ -5671,7 +5772,8 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
||||
{
|
||||
err = gen_card_key (3, get_parameter_algo (ctrl, para,
|
||||
pAUTHKEYTYPE, NULL ),
|
||||
0, pub_root, &authkeytimestamp, expire, keygen_flags);
|
||||
0, pub_root, &authkeytimestamp, expire,
|
||||
&keygen_flags);
|
||||
if (!err)
|
||||
err = write_keybinding (ctrl, pub_root, pri_psk, NULL,
|
||||
PUBKEY_USAGE_AUTH, signtimestamp, cache_nonce);
|
||||
@ -5681,7 +5783,6 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
||||
{
|
||||
int subkey_algo = get_parameter_algo (ctrl, para, pSUBKEYTYPE, NULL);
|
||||
|
||||
s = NULL;
|
||||
key_from_hexgrip = get_parameter_value (para, pSUBKEYGRIP);
|
||||
|
||||
keygen_flags = outctrl->keygen_flags;
|
||||
@ -5693,8 +5794,17 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
||||
key_from_hexgrip, cardkey,
|
||||
pub_root, subkeytimestamp,
|
||||
get_parameter_u32 (para, pSUBKEYEXPIRE),
|
||||
1, keygen_flags);
|
||||
else if (!card || (s = get_parameter_value (para, pCARDBACKUPKEY)))
|
||||
1, &keygen_flags);
|
||||
else if (get_parameter_value (para, pCARDBACKUPKEY))
|
||||
{
|
||||
int lastmode;
|
||||
unsigned int mykeygenflags = KEYGEN_FLAG_NO_PROTECTION;
|
||||
|
||||
err = agent_set_ephemeral_mode (ctrl, 1, &lastmode);
|
||||
if (err)
|
||||
log_error ("error switching to ephemeral mode: %s\n",
|
||||
gpg_strerror (err));
|
||||
else
|
||||
{
|
||||
err = do_create (subkey_algo,
|
||||
get_parameter_uint (para, pSUBKEYLENGTH),
|
||||
@ -5702,9 +5812,10 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
||||
pub_root,
|
||||
subkeytimestamp,
|
||||
get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
|
||||
s? KEYGEN_FLAG_NO_PROTECTION : keygen_flags,
|
||||
&mykeygenflags,
|
||||
get_parameter_passphrase (para),
|
||||
&cache_nonce, NULL);
|
||||
&cache_nonce, NULL,
|
||||
NULL, NULL);
|
||||
/* Get the pointer to the generated public subkey packet. */
|
||||
if (!err)
|
||||
{
|
||||
@ -5714,16 +5825,41 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
||||
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||
sub_psk = node->pkt->pkt.public_key;
|
||||
log_assert (sub_psk);
|
||||
|
||||
if (s)
|
||||
err = card_store_key_with_backup (ctrl,
|
||||
sub_psk, gnupg_homedir ());
|
||||
}
|
||||
|
||||
/* Reset the ephemeral mode as needed. */
|
||||
if (!lastmode && agent_set_ephemeral_mode (ctrl, 0, NULL))
|
||||
log_error ("error clearing the ephemeral mode\n");
|
||||
}
|
||||
}
|
||||
else if (!card)
|
||||
{
|
||||
err = do_create (subkey_algo,
|
||||
get_parameter_uint (para, pSUBKEYLENGTH),
|
||||
get_parameter_value (para, pSUBKEYCURVE),
|
||||
pub_root,
|
||||
subkeytimestamp,
|
||||
get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
|
||||
&keygen_flags,
|
||||
get_parameter_passphrase (para),
|
||||
&cache_nonce, NULL,
|
||||
NULL, NULL);
|
||||
if (!err)
|
||||
{
|
||||
kbnode_t node;
|
||||
|
||||
for (node = pub_root; node; node = node->next)
|
||||
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||
sub_psk = node->pkt->pkt.public_key;
|
||||
log_assert (sub_psk);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = gen_card_key (2, subkey_algo, 0, pub_root,
|
||||
&subkeytimestamp, expire, keygen_flags);
|
||||
&subkeytimestamp, expire, &keygen_flags);
|
||||
}
|
||||
|
||||
if (!err)
|
||||
@ -6097,7 +6233,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
|
||||
keyblock,
|
||||
keytime? keytime : cur_time,
|
||||
expire, 1,
|
||||
keygen_flags);
|
||||
&keygen_flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6113,8 +6249,8 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
|
||||
passwd = NULL;
|
||||
|
||||
err = do_create (algo, nbits, curve,
|
||||
keyblock, cur_time, expire, 1, keygen_flags,
|
||||
passwd, &cache_nonce, &passwd_nonce);
|
||||
keyblock, cur_time, expire, 1, &keygen_flags,
|
||||
passwd, &cache_nonce, &passwd_nonce, NULL, NULL);
|
||||
}
|
||||
if (err)
|
||||
goto leave;
|
||||
@ -6237,7 +6373,7 @@ generate_card_subkeypair (ctrl_t ctrl, kbnode_t pub_keyblock,
|
||||
/* Note, that depending on the backend, the card key generation may
|
||||
update CUR_TIME. */
|
||||
err = gen_card_key (keyno, algo, 0, pub_keyblock, &cur_time, expire,
|
||||
keygen_flags);
|
||||
&keygen_flags);
|
||||
/* Get the pointer to the generated public subkey packet. */
|
||||
if (!err)
|
||||
{
|
||||
@ -6283,11 +6419,10 @@ write_keyblock( IOBUF out, KBNODE node )
|
||||
}
|
||||
|
||||
|
||||
/* Note that timestamp is an in/out arg.
|
||||
* FIXME: Does not yet support v5 keys. */
|
||||
/* Note that timestamp is an in/out arg. */
|
||||
static gpg_error_t
|
||||
gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root,
|
||||
u32 *timestamp, u32 expireval, int keygen_flags)
|
||||
u32 *timestamp, u32 expireval, int *keygen_flags)
|
||||
{
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
gpg_error_t err;
|
||||
@ -6351,6 +6486,10 @@ gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Force creation of v5 keys for X448. */
|
||||
if (curve_is_448 (s_key))
|
||||
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
|
||||
|
||||
if (algo == PUBKEY_ALGO_RSA)
|
||||
err = key_from_sexp (pk->pkey, s_key, "public-key", "ne");
|
||||
else if (algo == PUBKEY_ALGO_ECDSA
|
||||
@ -6369,7 +6508,7 @@ gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root,
|
||||
}
|
||||
|
||||
pk->timestamp = *timestamp;
|
||||
pk->version = (keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
|
||||
pk->version = (*keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
|
||||
if (expireval)
|
||||
pk->expiredate = pk->timestamp + expireval;
|
||||
pk->pubkey_algo = algo;
|
||||
|
@ -408,6 +408,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
|
||||
#define IMPORT_COLLAPSE_UIDS (1<<15)
|
||||
#define IMPORT_COLLAPSE_SUBKEYS (1<<16)
|
||||
#define IMPORT_BULK (1<<17)
|
||||
#define IMPORT_IGNORE_ATTRIBUTES (1<<18)
|
||||
|
||||
#define EXPORT_LOCAL_SIGS (1<<0)
|
||||
#define EXPORT_ATTRIBUTES (1<<1)
|
||||
|
@ -2765,7 +2765,16 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
{
|
||||
ski->is_protected = 1;
|
||||
ski->s2k.count = 0;
|
||||
if (ski->algo == 254 || ski->algo == 255)
|
||||
if (ski->algo == 253)
|
||||
{
|
||||
if (list_mode)
|
||||
es_fprintf (listfp,
|
||||
"\tS2K pseudo algo %d is not yet supported\n",
|
||||
ski->algo);
|
||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
goto leave;
|
||||
}
|
||||
else if (ski->algo == 254 || ski->algo == 255)
|
||||
{
|
||||
if (pktlen < 3)
|
||||
{
|
||||
|
@ -444,8 +444,9 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Check compliance. */
|
||||
if (! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo))
|
||||
/* Check compliance but always allow for key revocations. */
|
||||
if (!IS_KEY_REV (sig)
|
||||
&& ! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo))
|
||||
{
|
||||
log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
|
||||
gcry_md_algo_name (mdalgo),
|
||||
@ -454,7 +455,8 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING,
|
||||
if (!IS_KEY_REV (sig)
|
||||
&& ! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING,
|
||||
pksk->pubkey_algo, 0,
|
||||
pksk->pkey, nbits_from_pk (pksk), NULL))
|
||||
{
|
||||
|
@ -433,10 +433,15 @@ static gpg_error_t
|
||||
mount_status_cb (void *opaque, const char *line)
|
||||
{
|
||||
struct mount_parm_s *parm = opaque;
|
||||
const char *s;
|
||||
|
||||
/* Nothing right now. */
|
||||
(void)parm;
|
||||
(void)line;
|
||||
|
||||
if ((s=has_leading_keyword (line, "PLAINDEV")))
|
||||
{
|
||||
if (opt.verbose || opt.no_mount)
|
||||
log_info ("Device: %s\n", s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -497,7 +502,10 @@ call_syshelp_run_mount (ctrl_t ctrl, int conttype, const char *mountpoint,
|
||||
{
|
||||
ref_tupledesc (tuples);
|
||||
parm.keyblob = get_tupledesc_data (tuples, &parm.keybloblen);
|
||||
err = assuan_transact (ctx, "MOUNT dm-crypt",
|
||||
err = assuan_transact (ctx,
|
||||
(opt.no_mount
|
||||
? "MOUNT --no-mount dm-crypt"
|
||||
: "MOUNT dm-crypt"),
|
||||
NULL, NULL,
|
||||
mount_inq_cb, &parm,
|
||||
mount_status_cb, &parm);
|
||||
|
@ -81,6 +81,8 @@ struct
|
||||
/* Name of the output file - FIXME: what is this? */
|
||||
const char *outfile;
|
||||
|
||||
int no_mount; /* Stop right before mounting a device. */
|
||||
|
||||
} opt;
|
||||
|
||||
|
||||
|
@ -583,7 +583,7 @@ g13_syshelp_i_know_what_i_am_doing (void)
|
||||
if (gnupg_access (fname, F_OK))
|
||||
{
|
||||
log_info ("*******************************************************\n");
|
||||
log_info ("* The G13 support for DM-Crypt is new and not matured.\n");
|
||||
log_info ("* The G13 support for DM-Crypt is not yet widely used.\n");
|
||||
log_info ("* Bugs or improper use may delete all your disks!\n");
|
||||
log_info ("* To confirm that you are ware of this risk, create\n");
|
||||
log_info ("* the file '%s'.\n", fname);
|
||||
|
@ -85,7 +85,7 @@ gpg_error_t sh_is_empty_partition (const char *name);
|
||||
gpg_error_t sh_dmcrypt_create_container (ctrl_t ctrl, const char *devname,
|
||||
estream_t devfp);
|
||||
gpg_error_t sh_dmcrypt_mount_container (ctrl_t ctrl, const char *devname,
|
||||
tupledesc_t keyblob);
|
||||
tupledesc_t keyblob, int nomount);
|
||||
gpg_error_t sh_dmcrypt_umount_container (ctrl_t ctrl, const char *devname);
|
||||
gpg_error_t sh_dmcrypt_suspend_container (ctrl_t ctrl, const char *devname);
|
||||
gpg_error_t sh_dmcrypt_resume_container (ctrl_t ctrl, const char *devname,
|
||||
|
@ -104,6 +104,7 @@ enum cmd_and_opt_values {
|
||||
oWithColons,
|
||||
oDryRun,
|
||||
oNoDetach,
|
||||
oNoMount,
|
||||
|
||||
oNoRandomSeedFile,
|
||||
oFakedSystemTime
|
||||
@ -138,6 +139,7 @@ static gpgrt_opt_t opts[] = {
|
||||
ARGPARSE_s_s (oLogFile, "log-file", N_("|FILE|write log output to FILE")),
|
||||
ARGPARSE_s_n (oNoLogFile, "no-log-file", "@"),
|
||||
ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
|
||||
ARGPARSE_s_n (oNoMount, "no-mount", N_("stop right before running mount")),
|
||||
|
||||
ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
|
||||
|
||||
@ -516,6 +518,8 @@ main (int argc, char **argv)
|
||||
|
||||
case oNoDetach: /*nodetach = 1; */break;
|
||||
|
||||
case oNoMount: opt.no_mount = 1; break;
|
||||
|
||||
case oDebug:
|
||||
if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
|
||||
{
|
||||
|
30
g13/sh-cmd.c
30
g13/sh-cmd.c
@ -83,17 +83,17 @@ skip_options (const char *line)
|
||||
|
||||
|
||||
/* Check whether the option NAME appears in LINE. */
|
||||
/* static int */
|
||||
/* has_option (const char *line, const char *name) */
|
||||
/* { */
|
||||
/* const char *s; */
|
||||
/* int n = strlen (name); */
|
||||
static int
|
||||
has_option (const char *line, const char *name)
|
||||
{
|
||||
const char *s;
|
||||
int n = strlen (name);
|
||||
|
||||
/* s = strstr (line, name); */
|
||||
/* if (s && s >= skip_options (line)) */
|
||||
/* return 0; */
|
||||
/* return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); */
|
||||
/* } */
|
||||
s = strstr (line, name);
|
||||
if (s && s >= skip_options (line))
|
||||
return 0;
|
||||
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
|
||||
}
|
||||
|
||||
|
||||
/* Helper to print a message while leaving a command. */
|
||||
@ -431,10 +431,11 @@ cmd_getkeyblob (assuan_context_t ctx, char *line)
|
||||
|
||||
|
||||
static const char hlp_mount[] =
|
||||
"MOUNT <type>\n"
|
||||
"MOUNT [--no-mount] <type>\n"
|
||||
"\n"
|
||||
"Mount an encrypted partition on the current device.\n"
|
||||
"<type> must be \"dm-crypt\" for now.";
|
||||
"<type> must be \"dm-crypt\" for now. Option --no-mount\n"
|
||||
"stops right before calling the mount command.\n";
|
||||
static gpg_error_t
|
||||
cmd_mount (assuan_context_t ctx, char *line)
|
||||
{
|
||||
@ -443,6 +444,9 @@ cmd_mount (assuan_context_t ctx, char *line)
|
||||
unsigned char *keyblob = NULL;
|
||||
size_t keybloblen;
|
||||
tupledesc_t tuples = NULL;
|
||||
int nomount;
|
||||
|
||||
nomount = has_option (line, "--no-mount");
|
||||
|
||||
line = skip_options (line);
|
||||
|
||||
@ -493,7 +497,7 @@ cmd_mount (assuan_context_t ctx, char *line)
|
||||
|
||||
err = sh_dmcrypt_mount_container (ctrl,
|
||||
ctrl->server_local->devicename,
|
||||
tuples);
|
||||
tuples, nomount);
|
||||
|
||||
leave:
|
||||
destroy_tupledesc (tuples);
|
||||
|
@ -220,7 +220,7 @@ mk_setup_area_prefix (size_t *r_length)
|
||||
}
|
||||
|
||||
|
||||
/* Create a new g13 styloe DM-Crypt container on devoce DEVNAME. */
|
||||
/* Create a new g13 style DM-Crypt container on device DEVNAME. */
|
||||
gpg_error_t
|
||||
sh_dmcrypt_create_container (ctrl_t ctrl, const char *devname, estream_t devfp)
|
||||
{
|
||||
@ -538,10 +538,11 @@ sh_dmcrypt_create_container (ctrl_t ctrl, const char *devname, estream_t devfp)
|
||||
|
||||
|
||||
/* Mount a DM-Crypt container on device DEVNAME taking keys and other
|
||||
* meta data from KEYBLOB. */
|
||||
* meta data from KEYBLOB. If NOMOUNT is set the actual mount command
|
||||
* is not run. */
|
||||
gpg_error_t
|
||||
sh_dmcrypt_mount_container (ctrl_t ctrl, const char *devname,
|
||||
tupledesc_t keyblob)
|
||||
tupledesc_t keyblob, int nomount)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char *targetname_abs = NULL;
|
||||
@ -696,8 +697,10 @@ sh_dmcrypt_mount_container (ctrl_t ctrl, const char *devname,
|
||||
xfree (result);
|
||||
result = NULL;
|
||||
|
||||
g13_status (ctrl, STATUS_PLAINDEV, targetname_abs, NULL);
|
||||
|
||||
/* Mount if a mountpoint has been given. */
|
||||
if (ctrl->devti->mountpoint)
|
||||
if (!nomount && ctrl->devti->mountpoint)
|
||||
{
|
||||
const char *argv[3];
|
||||
|
||||
@ -766,23 +769,32 @@ sh_dmcrypt_umount_container (ctrl_t ctrl, const char *devname)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Run the regular umount command. */
|
||||
/* Run the regular umount command but first test with findmnt. */
|
||||
{
|
||||
const char *argv[2];
|
||||
const char *argv[3];
|
||||
|
||||
argv[0] = targetname_abs;
|
||||
argv[1] = NULL;
|
||||
log_debug ("now running \"findmnt %s\"\n", targetname_abs);
|
||||
err = gnupg_exec_tool ("/bin/findmnt", argv, NULL, &result, NULL);
|
||||
|
||||
if (err)
|
||||
log_info ("Note: device was not mounted\n");
|
||||
else
|
||||
{
|
||||
xfree (result);
|
||||
result = NULL;
|
||||
|
||||
argv[0] = targetname_abs;
|
||||
argv[1] = NULL;
|
||||
log_debug ("now running \"umount %s\"\n", targetname_abs);
|
||||
err = gnupg_exec_tool ("/bin/umount", argv, NULL, &result, NULL);
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
log_error ("error running umount: %s\n", gpg_strerror (err));
|
||||
if (1)
|
||||
{
|
||||
/* Try to show some info about processes using the partition. */
|
||||
const char *argv[3];
|
||||
|
||||
argv[0] = "-mv";
|
||||
argv[1] = targetname_abs;
|
||||
argv[2] = NULL;
|
||||
@ -792,6 +804,8 @@ sh_dmcrypt_umount_container (ctrl_t ctrl, const char *devname)
|
||||
}
|
||||
if (result && *result) /* (We should not see output to stdout). */
|
||||
log_info ("WARNING: umount returned data on stdout! (%s)\n", result);
|
||||
}
|
||||
}
|
||||
xfree (result);
|
||||
result = NULL;
|
||||
|
||||
|
21
po/ca.po
21
po/ca.po
@ -810,8 +810,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Realment voleu eliminar les claus seleccionades? "
|
||||
|
||||
#, fuzzy
|
||||
@ -1953,16 +1953,16 @@ msgstr "no es pot usar un paquet asimètric ESK al estar en mode S2K\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "Ha fallat el procés de signatura: %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "«%s» ja està comprimida\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "AVÍS: «%s» és un fitxer buit\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "«%s» ja està comprimida\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "no podeu usar l'algorisme de resum %s mentre esteu en mode %s\n"
|
||||
@ -9496,6 +9496,9 @@ msgstr "S'ha creat el certificat de revocació.\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10682,8 +10685,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
23
po/cs.po
23
po/cs.po
@ -786,8 +786,8 @@ msgstr "Vyžádáno použití klíče%%0A %s%%0A %s%%0APřejete si to povolit?
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr ""
|
||||
"Opravdu chcete smazat klíč určený pomocí keygripu%%0A %s%%0A %%C%%0A?"
|
||||
|
||||
@ -1831,14 +1831,14 @@ msgstr "v režimu S2K nelze použít SKESK paket\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "použití šifry %s.%s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "„%s“ je již zkomprimován\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "POZOR: soubor „%s“ je prázdný\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "„%s“ je již zkomprimován\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "hashovací algoritmus „%s“ se nesmí používat v režimu %s\n"
|
||||
@ -8974,6 +8974,9 @@ msgstr "uloží certifikát do datového objektu"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr "uloží soukromý klíč do datového objektu"
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr "Příkazy pro správu Yubikey"
|
||||
|
||||
@ -10568,8 +10571,8 @@ msgstr "spravuje historii příkazů"
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
@ -10616,8 +10619,8 @@ msgstr "spravuje historii příkazů"
|
||||
#~ "Answer \"yes\" if you really want to delete this user ID.\n"
|
||||
#~ "All certificates are then also lost!"
|
||||
#~ msgstr ""
|
||||
#~ "Pokud opravdu chcete smazat tento identifikátor uživatele, odpovězte \"ano"
|
||||
#~ "\".\n"
|
||||
#~ "Pokud opravdu chcete smazat tento identifikátor uživatele, odpovězte "
|
||||
#~ "\"ano\".\n"
|
||||
#~ "Všechny certifikáty budou také ztraceny!"
|
||||
|
||||
#~ msgid "Answer \"yes\" if it is okay to delete the subkey"
|
||||
|
25
po/da.po
25
po/da.po
@ -259,8 +259,8 @@ msgid ""
|
||||
"Please enter a passphrase to protect the received secret key%%0A %s%%0A "
|
||||
"%s%%0Awithin gpg-agent's key storage"
|
||||
msgstr ""
|
||||
"Indtast venligst en adgangsfrase for at beskytte den modtaget hemmelige nøgle"
|
||||
"%%0A %s%%0A %s%%0Ainden i gpg-agentens nøglelager"
|
||||
"Indtast venligst en adgangsfrase for at beskytte den modtaget hemmelige "
|
||||
"nøgle%%0A %s%%0A %s%%0Ainden i gpg-agentens nøglelager"
|
||||
|
||||
#, c-format
|
||||
msgid "failed to create stream from socket: %s\n"
|
||||
@ -868,8 +868,8 @@ msgstr ""
|
||||
#, fuzzy, c-format
|
||||
#| msgid "Do you really want to delete the selected keys? (y/N) "
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Vil du virkelig slette de valgte nøgler? (j/N) "
|
||||
|
||||
#, fuzzy
|
||||
@ -1995,16 +1995,16 @@ msgstr "kan ikke bruge en symmetrisk ESK-pakke på grund af S2K-tilstanden\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "bruger chiffer %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "»%s« allerede komprimeret\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "ADVARSEL: »%s« er en tom fil\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "»%s« allerede komprimeret\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "you may not use digest algorithm `%s' while in %s mode\n"
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
@ -2527,8 +2527,8 @@ msgstr "ADVARSEL: Usikre indelukkede mapperettigheder på hjemmemappe »%s«\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid ""
|
||||
#| "WARNING: unsafe enclosing directory permissions on configuration file `"
|
||||
#| "%s'\n"
|
||||
#| "WARNING: unsafe enclosing directory permissions on configuration file "
|
||||
#| "`%s'\n"
|
||||
msgid ""
|
||||
"WARNING: unsafe enclosing directory permissions on configuration file '%s'\n"
|
||||
msgstr ""
|
||||
@ -9711,6 +9711,9 @@ msgstr " (certifkat oprettet den "
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
|
36
po/de.po
36
po/de.po
@ -9,7 +9,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnupg-2.4.1\n"
|
||||
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
||||
"PO-Revision-Date: 2023-05-30 13:46+0200\n"
|
||||
"PO-Revision-Date: 2024-01-24 14:05+0100\n"
|
||||
"Last-Translator: Werner Koch <wk@gnupg.org>\n"
|
||||
"Language-Team: German\n"
|
||||
"Language: de\n"
|
||||
@ -230,8 +230,9 @@ msgid ""
|
||||
"Please enter a passphrase to protect the received secret key%%0A %s%%0A "
|
||||
"%s%%0Awithin gpg-agent's key storage"
|
||||
msgstr ""
|
||||
"Bitte geben Sie ein Passwort ein, um den empfangenen geheimen Schlüssel"
|
||||
"%%0A %s%%0A %s%%0Aim Schlüsselspeicher des Gpg-Agenten zu schützen."
|
||||
"Bitte geben Sie ein Passwort ein, um den empfangenen geheimen "
|
||||
"Schlüssel%%0A %s%%0A %s%%0Aim Schlüsselspeicher des Gpg-Agenten zu "
|
||||
"schützen."
|
||||
|
||||
#, c-format
|
||||
msgid "failed to create stream from socket: %s\n"
|
||||
@ -710,9 +711,9 @@ msgid ""
|
||||
"Do you ultimately trust%%0A \"%s\"%%0Ato correctly certify user "
|
||||
"certificates?"
|
||||
msgstr ""
|
||||
"Wenn Sie vollständiges Vertrauen haben, daß%%0A \"%s"
|
||||
"\"%%0ABenutzerzertifikate verläßlich zertifiziert, so antworten Sie mit \"Ja"
|
||||
"\"."
|
||||
"Wenn Sie vollständiges Vertrauen haben, daß%%0A "
|
||||
"\"%s\"%%0ABenutzerzertifikate verläßlich zertifiziert, so antworten Sie mit "
|
||||
"\"Ja\"."
|
||||
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
@ -776,8 +777,8 @@ msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr ""
|
||||
"Möchten Sie den Schlüssel mit dem \"Keygrip\"%%0A %s%%0A %%C%%0Awirklich "
|
||||
"entfernen?"
|
||||
@ -1837,14 +1838,14 @@ msgstr "Aufgrund des S2K-Modus kann ein SKESK Paket nicht benutzt werden\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "benutze Cipher %s.%s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' ist bereits komprimiert\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "WARNUNG: '%s' ist eine leere Datei.\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' ist bereits komprimiert\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "Die Benutzung der Hashmethode %s ist im %s Modus nicht erlaubt.\n"
|
||||
@ -9106,6 +9107,9 @@ msgstr "Ein Zertifikat in einem Datenobjekt speichern"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr "Privaten Schlüssel in einem Datenobjekt speichern"
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr "Die Schlüssel verschiedener Prüfungen unterziehen"
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr "Verwaltungskommandos für Yubikeys"
|
||||
|
||||
@ -10484,8 +10488,8 @@ msgstr "Verwaltung der Kommandohistorie"
|
||||
|
||||
#~ msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n"
|
||||
#~ msgstr ""
|
||||
#~ "Die \"Trust\"-Datenbank ist beschädigt; verwenden Sie \"gpg --fix-trustdb"
|
||||
#~ "\".\n"
|
||||
#~ "Die \"Trust\"-Datenbank ist beschädigt; verwenden Sie \"gpg --fix-"
|
||||
#~ "trustdb\".\n"
|
||||
|
||||
#~ msgid "Please report bugs to <"
|
||||
#~ msgstr "Fehlerberichte bitte an <"
|
||||
@ -10710,8 +10714,8 @@ msgstr "Verwaltung der Kommandohistorie"
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
21
po/el.po
21
po/el.po
@ -777,8 +777,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Σίγουρα θέλετε να διαγραφούν τα επιλεγμένα κλειδιά; "
|
||||
|
||||
#, fuzzy
|
||||
@ -1885,16 +1885,16 @@ msgstr "αδυναμία χρήσης ενός συμμετρικού πακέτ
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "χρήση του κρυπταλγόριθμου: %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' ήδη συμπιέστηκε\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: `%s' είναι ένα άδειο αρχείο\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' ήδη συμπιέστηκε\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr ""
|
||||
@ -9320,6 +9320,9 @@ msgstr "Πιστοποιητικό ανάκλησης δημιουργήθηκε
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10489,8 +10492,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
21
po/eo.po
21
po/eo.po
@ -776,8 +776,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Ĉu vi vere volas forviŝi la elektitajn ŝlosilojn? "
|
||||
|
||||
#, fuzzy
|
||||
@ -1878,16 +1878,16 @@ msgstr ""
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "subskribado malsukcesis: %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' jam densigita\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "AVERTO: '%s' estas malplena dosiero\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' jam densigita\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "Tiu komando ne eblas en la reĝimo %s.\n"
|
||||
@ -9231,6 +9231,9 @@ msgstr "ŝlosilo %08lX: revokatestilo aldonita\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10312,8 +10315,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
31
po/es.po
31
po/es.po
@ -776,8 +776,8 @@ msgid ""
|
||||
"Please verify that the certificate identified as:%%0A \"%s\"%%0Ahas the "
|
||||
"fingerprint:%%0A %s"
|
||||
msgstr ""
|
||||
"Por favor verifique que el certificado identificado como:%%0A \"%s"
|
||||
"\"%%0Atiene la huella digital:%%0A %s"
|
||||
"Por favor verifique que el certificado identificado como:%%0A "
|
||||
"\"%s\"%%0Atiene la huella digital:%%0A %s"
|
||||
|
||||
#. TRANSLATORS: "Correct" is the label of a button and intended
|
||||
#. to be hit if the fingerprint matches the one of the CA. The
|
||||
@ -821,8 +821,8 @@ msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr ""
|
||||
"¿De verdad quiere borrar la clave identificada con el keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
@ -1889,14 +1889,14 @@ msgstr "no puede usar un paquete simétrico ESK debido al modo S2K\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "usando cifrado %s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' ya está comprimido\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "ATENCIÓN '%s' es un fichero vacío\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' ya está comprimido\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "no puede usar el resumen '%s' en modo %s\n"
|
||||
@ -5704,8 +5704,8 @@ msgstr ""
|
||||
"la clave secreta. De cualquier modo, si la clave secreta está disponible,\n"
|
||||
"es mejor generar un nuevo certificado de revocación y dar una razón para la "
|
||||
"misma\n"
|
||||
"Para más detalles, lee la descripción de la orden gpg \"--generate-revocation"
|
||||
"\"\n"
|
||||
"Para más detalles, lee la descripción de la orden gpg \"--generate-"
|
||||
"revocation\"\n"
|
||||
"en el manual GnuPG."
|
||||
|
||||
msgid ""
|
||||
@ -9157,6 +9157,9 @@ msgstr "añadir un certificado a la cache"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10532,8 +10535,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
@ -10572,8 +10575,8 @@ msgstr ""
|
||||
#~ " al poseedor de la clave.\n"
|
||||
#~ "\n"
|
||||
#~ "Observe que los ejemplos dados en los niveles 2 y 3 son *solo* ejemplos.\n"
|
||||
#~ "En definitiva, usted decide lo que significa \"informal\" y \"exhaustivo"
|
||||
#~ "\"\n"
|
||||
#~ "En definitiva, usted decide lo que significa \"informal\" y "
|
||||
#~ "\"exhaustivo\"\n"
|
||||
#~ "para usted cuando firma las claves de otros.\n"
|
||||
#~ "\n"
|
||||
#~ "Si no sabe qué contestar, conteste \"0\"."
|
||||
|
25
po/et.po
25
po/et.po
@ -774,8 +774,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Kas te tõesti soovite valitud võtmeid kustutada? "
|
||||
|
||||
#, fuzzy
|
||||
@ -1879,16 +1879,16 @@ msgstr "S2K moodi tõttu ei saa sümmeetrilist ESK paketti kasutada\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "kasutan šiffrit %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' on juba pakitud\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "HOIATUS: `%s' on tühi fail\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' on juba pakitud\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "sõnumilühendi algoritm \"%s\" ei ole moodis %s lubatud\n"
|
||||
@ -9235,6 +9235,9 @@ msgstr "Tühistamise sertifikaat on loodud.\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10276,8 +10279,8 @@ msgstr ""
|
||||
|
||||
#~ msgid "If you want to use this untrusted key anyway, answer \"yes\"."
|
||||
#~ msgstr ""
|
||||
#~ "Kui te ikkagi soovite kasutada seda mitteusaldatavat võtit, vastake \"jah"
|
||||
#~ "\"."
|
||||
#~ "Kui te ikkagi soovite kasutada seda mitteusaldatavat võtit, vastake "
|
||||
#~ "\"jah\"."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Enter the user ID of the addressee to whom you want to send the message."
|
||||
@ -10373,8 +10376,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
21
po/fi.po
21
po/fi.po
@ -791,8 +791,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Haluatko varmasti poistaa valitut avaimet? "
|
||||
|
||||
#, fuzzy
|
||||
@ -1897,16 +1897,16 @@ msgstr "symmetristä ESK-pakettia ei voi käyttää S2K-tilan vuoksi\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "käytetään salakirjoitusalgoritmia %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "\"%s\" on jo pakattu\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "VAROITUS: \"%s\" on tyhjä tiedosto\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "\"%s\" on jo pakattu\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "tiivistealgoritmia \"%s\" ei voi käyttää %s-tilassa\n"
|
||||
@ -9303,6 +9303,9 @@ msgstr "Mitätöintivarmenne luotu.\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10465,8 +10468,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
23
po/fr.po
23
po/fr.po
@ -246,8 +246,8 @@ msgid ""
|
||||
"Please enter a passphrase to protect the received secret key%%0A %s%%0A "
|
||||
"%s%%0Awithin gpg-agent's key storage"
|
||||
msgstr ""
|
||||
"Veuillez entrer une phrase secrète pour protéger la clef secrète%%0A %s"
|
||||
"%%0A %s%%0Areçue dans l'espace de stockage de clefs de gpg-agent"
|
||||
"Veuillez entrer une phrase secrète pour protéger la clef secrète%%0A "
|
||||
"%s%%0A %s%%0Areçue dans l'espace de stockage de clefs de gpg-agent"
|
||||
|
||||
#, c-format
|
||||
msgid "failed to create stream from socket: %s\n"
|
||||
@ -824,8 +824,8 @@ msgstr ""
|
||||
#, fuzzy, c-format
|
||||
#| msgid "Do you really want to delete the selected keys? (y/N) "
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Voulez-vous vraiment supprimer les clefs sélectionnées ? (o/N) "
|
||||
|
||||
msgid "Delete key"
|
||||
@ -1931,14 +1931,14 @@ msgstr "impossible d'utiliser un paquet ESK symétrique en mode S2K\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "utilisation de l'algorithme de chiffrement %s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "« %s » est déjà compressé\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "Attention : « %s » est un fichier vide\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "« %s » est déjà compressé\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "you may not use digest algorithm '%s' while in %s mode\n"
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
@ -9514,6 +9514,9 @@ msgstr "ajouter un certificat au cache"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10997,8 +11000,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
29
po/gl.po
29
po/gl.po
@ -779,8 +779,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "¿Seguro de que quere borra-las chaves seleccionadas? "
|
||||
|
||||
#, fuzzy
|
||||
@ -1889,16 +1889,16 @@ msgstr "non se pode empregar un paquete simétrico ESK debido ao modo S2K\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "fallou a sinatura: %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' xa está comprimido\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "AVISO: `%s' é un ficheiro baleiro\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' xa está comprimido\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "non se pode empregar o algoritmo de resumo \"%s\" no modo %s\n"
|
||||
@ -3173,8 +3173,8 @@ msgstr "chave %08lX: non hai ID de usuario para a sinatura\n"
|
||||
#, fuzzy, c-format
|
||||
msgid "key %s: unsupported public key algorithm on user ID \"%s\"\n"
|
||||
msgstr ""
|
||||
"chave %08lX: algoritmo de chave pública non soportado no ID de usuario \"%s"
|
||||
"\"\n"
|
||||
"chave %08lX: algoritmo de chave pública non soportado no ID de usuario "
|
||||
"\"%s\"\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "key %s: invalid self-signature on user ID \"%s\"\n"
|
||||
@ -9315,6 +9315,9 @@ msgstr "Creouse o certificado de revocación.\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10302,8 +10305,8 @@ msgstr ""
|
||||
|
||||
#~ msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n"
|
||||
#~ msgstr ""
|
||||
#~ "a base de datos de confianza está corrompida; execute \"gpg --fix-trustdb"
|
||||
#~ "\".\n"
|
||||
#~ "a base de datos de confianza está corrompida; execute \"gpg --fix-"
|
||||
#~ "trustdb\".\n"
|
||||
|
||||
#~ msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n"
|
||||
#~ msgstr ""
|
||||
@ -10483,8 +10486,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
21
po/hu.po
21
po/hu.po
@ -774,8 +774,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Valóban törli a kiválasztott kulcsokat? "
|
||||
|
||||
#, fuzzy
|
||||
@ -1880,16 +1880,16 @@ msgstr "Nem tudok szimmetrikus ESK csomagot használni a S2K mód miatt!\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "%s rejtjelezést használok.\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "\"%s\" már tömörített.\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "FIGYELEM: A(z) \"%s\" állomány üres.\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "\"%s\" már tömörített.\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr ""
|
||||
@ -9262,6 +9262,9 @@ msgstr "Visszavonó igazolás létrehozva.\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10418,8 +10421,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
21
po/id.po
21
po/id.po
@ -779,8 +779,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Anda ingin menghapus kunci terpilih ini? "
|
||||
|
||||
#, fuzzy
|
||||
@ -1886,16 +1886,16 @@ msgstr "tidak dapat menggunakan paket simetri ESK karena mode S2K\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "menggunakan cipher %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' sudah dikompresi\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "PERINGATAN: `%s' adalah file kosong\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' sudah dikompresi\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr ""
|
||||
@ -9261,6 +9261,9 @@ msgstr "Sertifikat pembatalan tercipta.\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10418,8 +10421,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
19
po/it.po
19
po/it.po
@ -225,8 +225,8 @@ msgid ""
|
||||
"Please enter a passphrase to protect the received secret key%%0A %s%%0A "
|
||||
"%s%%0Awithin gpg-agent's key storage"
|
||||
msgstr ""
|
||||
"Immettere una passphrase per proteggere la chiave segreta ricevuta%%0A %s"
|
||||
"%%0A %s%%0A all'interno dell'archivio chiavi dell'agente gpg"
|
||||
"Immettere una passphrase per proteggere la chiave segreta ricevuta%%0A "
|
||||
"%s%%0A %s%%0A all'interno dell'archivio chiavi dell'agente gpg"
|
||||
|
||||
#, c-format
|
||||
msgid "failed to create stream from socket: %s\n"
|
||||
@ -771,8 +771,8 @@ msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr ""
|
||||
"Si desidera eliminare la chiave identificata da keygrip%%0A %s%%0A %%C%%0A?"
|
||||
|
||||
@ -1828,14 +1828,14 @@ msgstr ""
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "utilizzando il cifrario %s.%s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' già compresso\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "AVVISO: '%s' è un file vuoto\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' già compresso\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "l'algoritmo digest '%s' non può essere utilizzato in modalità %s\n"
|
||||
@ -9069,6 +9069,9 @@ msgstr "archiviare un certificato in un oggetto dati"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr "archiviare una chiave privata in un oggetto dati"
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr "Comandi di gestione Yubikey"
|
||||
|
||||
|
7
po/ja.po
7
po/ja.po
@ -5,13 +5,13 @@
|
||||
# Yoshihiro Kajiki <kajiki@ylug.org>, 1999.
|
||||
# Takashi P.KATOH, 2002.
|
||||
# NIIBE Yutaka <gniibe@fsij.org>, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
||||
# 2020, 2021, 2022, 2023.
|
||||
# 2020, 2021, 2022, 2023, 2024.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnupg 2.4.3\n"
|
||||
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
||||
"PO-Revision-Date: 2023-11-20 10:50+0900\n"
|
||||
"PO-Revision-Date: 2024-01-25 09:06+0900\n"
|
||||
"Last-Translator: NIIBE Yutaka <gniibe@fsij.org>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ja\n"
|
||||
@ -8729,6 +8729,9 @@ msgstr "証明書をデータオブジェクトに保管します"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr "プライベート鍵をデータオブジェクトに保管する"
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr "鍵に対して様々なチェックを実行する"
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr "Yubikey管理コマンド"
|
||||
|
||||
|
19
po/nb.po
19
po/nb.po
@ -237,8 +237,8 @@ msgid ""
|
||||
"Please enter a passphrase to protect the received secret key%%0A %s%%0A "
|
||||
"%s%%0Awithin gpg-agent's key storage"
|
||||
msgstr ""
|
||||
"Skriv inn passordfrase som skal brukes til å beskytte mottatt hemmelig nøkkel"
|
||||
"%%0A %s%%0A %s%%0Ai nøkkellageret for gpg-agent"
|
||||
"Skriv inn passordfrase som skal brukes til å beskytte mottatt hemmelig "
|
||||
"nøkkel%%0A %s%%0A %s%%0Ai nøkkellageret for gpg-agent"
|
||||
|
||||
#, c-format
|
||||
msgid "failed to create stream from socket: %s\n"
|
||||
@ -782,8 +782,8 @@ msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr ""
|
||||
"Er du sikker på at du vil slette nøkkel med nøkkelgrep%%0A %s%%0A %%C%%0A?"
|
||||
|
||||
@ -1858,14 +1858,14 @@ msgstr "klarte ikke å bruke symmetrisk ESK-pakke på grunn av S2K-modus\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "bruker krypteringsmetode %s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "«%s» er allerede komprimert\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "ADVARSEL: «%s» er en tom fil\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "«%s» er allerede komprimert\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "du kan ikke bruke algoritme «%s» i %s-modus\n"
|
||||
@ -9046,6 +9046,9 @@ msgstr "legg til sertifikat i hurtiglager"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
|
31
po/pt.po
31
po/pt.po
@ -881,8 +881,28 @@ msgid "waiting for process %d to terminate failed: %s\n"
|
||||
msgstr "falha ao aguardar pelo encerramento do processo %d: %s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "waiting for process to terminate failed: ec=%d\n"
|
||||
msgstr "falha ao esperar que o processo terminasse: ec=%d\n"
|
||||
msgid "error running '%s': probably not installed\n"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "error accessing '%s': http status %u\n"
|
||||
msgid "error running '%s': exit status %d\n"
|
||||
msgstr "erro ao aceder '%s': status http %u\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "error opening '%s': %s\n"
|
||||
msgid "error running '%s': terminated\n"
|
||||
msgstr "erro ao abrir '%s': %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "waiting for process %d to terminate failed: %s\n"
|
||||
msgid "waiting for processes to terminate failed: %s\n"
|
||||
msgstr "falha ao aguardar pelo encerramento do processo %d: %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "error getting list of cards: %s\n"
|
||||
msgid "error getting exit code of process %d: %s\n"
|
||||
msgstr "erro ao obter a lista de cartões: %s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "can't connect to '%s': %s\n"
|
||||
@ -8968,8 +8988,15 @@ msgstr "armazenar um certificado em um objeto de dados"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr "armazenar uma chave privada em um objeto de dados"
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr "comandos de gerir uma Yubikey"
|
||||
|
||||
msgid "manage the command history"
|
||||
msgstr "gerir o histórico de comandos"
|
||||
|
||||
#, c-format
|
||||
#~ msgid "waiting for process to terminate failed: ec=%d\n"
|
||||
#~ msgstr "falha ao esperar que o processo terminasse: ec=%d\n"
|
||||
|
33
po/ro.po
33
po/ro.po
@ -792,8 +792,8 @@ msgstr ""
|
||||
#, fuzzy, c-format
|
||||
#| msgid "Do you really want to delete the selected keys? (y/N) "
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Doriţi într-adevăr să ştergeţi cheile selectate? (d/N) "
|
||||
|
||||
#, fuzzy
|
||||
@ -1908,16 +1908,16 @@ msgstr "nu pot crea un pachet ESK simetric datorită modului S2K\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "folosesc cifrul %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' deja compresat\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "AVERTISMENT: `%s' este un fişier gol\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' deja compresat\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "you may not use digest algorithm `%s' while in %s mode\n"
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
@ -2449,8 +2449,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid ""
|
||||
#| "WARNING: unsafe enclosing directory permissions on configuration file `"
|
||||
#| "%s'\n"
|
||||
#| "WARNING: unsafe enclosing directory permissions on configuration file "
|
||||
#| "`%s'\n"
|
||||
msgid ""
|
||||
"WARNING: unsafe enclosing directory permissions on configuration file '%s'\n"
|
||||
msgstr ""
|
||||
@ -3236,8 +3236,8 @@ msgstr "cheia %s: nici un ID utilizator pentru semnătură\n"
|
||||
#, c-format
|
||||
msgid "key %s: unsupported public key algorithm on user ID \"%s\"\n"
|
||||
msgstr ""
|
||||
"cheia %s: algoritm cu cheie publică nesuportat pentru ID-ul utilizator \"%s"
|
||||
"\"\n"
|
||||
"cheia %s: algoritm cu cheie publică nesuportat pentru ID-ul utilizator "
|
||||
"\"%s\"\n"
|
||||
|
||||
#, c-format
|
||||
msgid "key %s: invalid self-signature on user ID \"%s\"\n"
|
||||
@ -9406,6 +9406,9 @@ msgstr "Certificat de revocare creat.\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10620,8 +10623,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
@ -11539,8 +11542,8 @@ msgstr ""
|
||||
#~ "crea\n"
|
||||
#~ "o cheie sigură pentru semnături: acest program face acest lucru, dar "
|
||||
#~ "alte\n"
|
||||
#~ "implementări OpenPGP ar putea să nu înţeleagă varianta de semnare"
|
||||
#~ "+cifrare.\n"
|
||||
#~ "implementări OpenPGP ar putea să nu înţeleagă varianta de "
|
||||
#~ "semnare+cifrare.\n"
|
||||
#~ "\n"
|
||||
#~ "Prima cheie (primară) trebuie să fie întotdeauna capabilă de semnare;\n"
|
||||
#~ "acesta este motivul pentru care cheia ElGamal nu este disponibilă în\n"
|
||||
|
27
po/ru.po
27
po/ru.po
@ -18,8 +18,8 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11) ? 0 : ((n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20)) ? 1 : 2);\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11) ? 0 : ((n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20)) ? 1 : 2);\n"
|
||||
|
||||
#, c-format
|
||||
msgid "failed to acquire the pinentry lock: %s\n"
|
||||
@ -328,8 +328,8 @@ msgstr[2] ""
|
||||
#, c-format
|
||||
msgid "A passphrase may not be a known term or match%%0Acertain pattern."
|
||||
msgstr ""
|
||||
"Фраза-пароль не должна быть известным выражением и не должна быть составлена"
|
||||
"%%0Aпо определенному образцу."
|
||||
"Фраза-пароль не должна быть известным выражением и не должна быть "
|
||||
"составлена%%0Aпо определенному образцу."
|
||||
|
||||
msgid "Warning: You have entered an insecure passphrase."
|
||||
msgstr "Внимание: Вы ввели небезопасную фразу-пароль."
|
||||
@ -786,8 +786,8 @@ msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Вы действительно хотите удалить ключ с кодом%%0A %s%%0A %%C%%0A?"
|
||||
|
||||
msgid "Delete key"
|
||||
@ -1843,14 +1843,14 @@ msgstr "не могу использовать симметричный паке
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "используется симметричный шифр %s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' уже сжат\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "Внимание: файл '%s' пуст\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' уже сжат\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "хеш-функцию '%s' нельзя использовать в режиме %s\n"
|
||||
@ -9147,6 +9147,9 @@ msgstr "добавить сертификат в буфер"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -9617,8 +9620,8 @@ msgstr ""
|
||||
|
||||
#~ msgid "error setting policy for key %s, user id \"%s\": %s"
|
||||
#~ msgstr ""
|
||||
#~ "ошибка установки правил для ключа %s с идентификатором пользователя \"%s"
|
||||
#~ "\": %s"
|
||||
#~ "ошибка установки правил для ключа %s с идентификатором пользователя "
|
||||
#~ "\"%s\": %s"
|
||||
|
||||
#~ msgid "only SHA-1 is supported for OCSP responses\n"
|
||||
#~ msgstr "для ответов OCSP поддерживается только SHA-1\n"
|
||||
|
29
po/sk.po
29
po/sk.po
@ -779,8 +779,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Skutočne chcete zmazať vybrané kľúče? "
|
||||
|
||||
#, fuzzy
|
||||
@ -1886,16 +1886,16 @@ msgstr "v móde S2K nemožno použiť symetrický ESK paket\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "použitá šifra %s\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' je už skomprimovaný\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "VAROVANIE: súbor `%s' je prázdny\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "`%s' je už skomprimovaný\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "nemôžete použiť hashovací algoritmus \"%s\" v móde %s\n"
|
||||
@ -3180,8 +3180,8 @@ msgstr "kľúč %08lX: neexistuje id užívateľa pre podpis\n"
|
||||
#, fuzzy, c-format
|
||||
msgid "key %s: unsupported public key algorithm on user ID \"%s\"\n"
|
||||
msgstr ""
|
||||
"kľúč %08lX: nepodporovaný algoritmus verejného kľúča u užívateľského id \"%s"
|
||||
"\"\n"
|
||||
"kľúč %08lX: nepodporovaný algoritmus verejného kľúča u užívateľského id "
|
||||
"\"%s\"\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "key %s: invalid self-signature on user ID \"%s\"\n"
|
||||
@ -9295,6 +9295,9 @@ msgstr "Revokačný certifikát bol vytvorený.\n"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -10452,8 +10455,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
@ -10496,8 +10499,8 @@ msgstr ""
|
||||
#, fuzzy
|
||||
#~ msgid "Answer \"yes\" if you want to sign ALL the user IDs"
|
||||
#~ msgstr ""
|
||||
#~ "Pokiaľ chcete podpísať VŠETKY identifikátory užívateľov, odpovedzte \"ano"
|
||||
#~ "\""
|
||||
#~ "Pokiaľ chcete podpísať VŠETKY identifikátory užívateľov, odpovedzte "
|
||||
#~ "\"ano\""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Answer \"yes\" if you really want to delete this user ID.\n"
|
||||
|
25
po/sv.po
25
po/sv.po
@ -881,8 +881,8 @@ msgstr ""
|
||||
#, fuzzy, c-format
|
||||
#| msgid "Do you really want to delete the selected keys? (y/N) "
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "Vill du verkligen ta bort de valda nycklarna? (j/N) "
|
||||
|
||||
#, fuzzy
|
||||
@ -2026,16 +2026,16 @@ msgstr "kan inte använda symmetriska ESK-paket pga S2K-läge\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "använder %s-chiffer\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "\"%s\" är redan komprimerad\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "WARNING: `%s' is an empty file\n"
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "VARNING: \"%s\" är en tom fil\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "`%s' already compressed\n"
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "\"%s\" är redan komprimerad\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "you may not use digest algorithm `%s' while in %s mode\n"
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
@ -2570,8 +2570,8 @@ msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid ""
|
||||
#| "WARNING: unsafe enclosing directory permissions on configuration file `"
|
||||
#| "%s'\n"
|
||||
#| "WARNING: unsafe enclosing directory permissions on configuration file "
|
||||
#| "`%s'\n"
|
||||
msgid ""
|
||||
"WARNING: unsafe enclosing directory permissions on configuration file '%s'\n"
|
||||
msgstr ""
|
||||
@ -9851,6 +9851,9 @@ msgstr " (certifikat skapat "
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
@ -11212,8 +11215,8 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Note that the examples given above for levels 2 and 3 are *only* "
|
||||
#~ "examples.\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and \"extensive"
|
||||
#~ "\"\n"
|
||||
#~ "In the end, it is up to you to decide just what \"casual\" and "
|
||||
#~ "\"extensive\"\n"
|
||||
#~ "mean to you when you sign other keys.\n"
|
||||
#~ "\n"
|
||||
#~ "If you don't know what the right answer is, answer \"0\"."
|
||||
|
15
po/tr.po
15
po/tr.po
@ -762,8 +762,8 @@ msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr ""
|
||||
"%%0A %s%%0A %%C%%0A anahtar maşası tarafından tanımlanan anahtarı silmek "
|
||||
"istediğnizden emin misiniz?"
|
||||
@ -1799,14 +1799,14 @@ msgstr "S2K kipi nedeniyle bir SKESK paketi kullanılamıyor\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "%s.%s şifrelemesi kullanılıyor\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' halihazırda sıkıştırılmış\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "UYARI: '%s', boş bir dosya\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' halihazırda sıkıştırılmış\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "özet algoritması '%s', %s kipinde kullanılamayabilir\n"
|
||||
@ -8910,6 +8910,9 @@ msgstr "bir veri nesnesine bir sertifika depola"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr "bir veri nesnesine bir özel anahtar depola"
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr "Yubikey yönetim konsolu"
|
||||
|
||||
|
23
po/uk.po
23
po/uk.po
@ -14,8 +14,8 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11) ? 0 : ((n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20)) ? 1 : 2);\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11) ? 0 : ((n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20)) ? 1 : 2);\n"
|
||||
"X-Generator: Lokalize 20.11.70\n"
|
||||
|
||||
#, c-format
|
||||
@ -235,8 +235,8 @@ msgid ""
|
||||
"Please enter a passphrase to protect the received secret key%%0A %s%%0A "
|
||||
"%s%%0Awithin gpg-agent's key storage"
|
||||
msgstr ""
|
||||
"Будь ласка, вкажіть пароль для захисту отриманого закритого ключа%%0A %s"
|
||||
"%%0A %s%%0Aу сховищі ключів gpg-agent"
|
||||
"Будь ласка, вкажіть пароль для захисту отриманого закритого ключа%%0A "
|
||||
"%s%%0A %s%%0Aу сховищі ключів gpg-agent"
|
||||
|
||||
#, c-format
|
||||
msgid "failed to create stream from socket: %s\n"
|
||||
@ -787,8 +787,8 @@ msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr ""
|
||||
"Справді хочете вилучити ключ, що визначається keygrip%%0A %s%%0A %%C%%0A?"
|
||||
|
||||
@ -1860,14 +1860,14 @@ msgstr "не можна використовувати симетричний п
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "використано шифр %s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "«%s» вже стиснено\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "УВАГА: файл «%s» є порожнім\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "«%s» вже стиснено\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr ""
|
||||
@ -9240,6 +9240,9 @@ msgstr "додати сертифікат до кешу"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
|
19
po/zh_CN.po
19
po/zh_CN.po
@ -221,8 +221,8 @@ msgid ""
|
||||
"Please enter a passphrase to protect the received secret key%%0A %s%%0A "
|
||||
"%s%%0Awithin gpg-agent's key storage"
|
||||
msgstr ""
|
||||
"请输入一个密码,以便于在 gpg-agent 的密钥存储中保护接收到的私钥 %%0A %s"
|
||||
"%%0A %s%%0A"
|
||||
"请输入一个密码,以便于在 gpg-agent 的密钥存储中保护接收到的私钥 %%0A "
|
||||
"%s%%0A %s%%0A"
|
||||
|
||||
#, c-format
|
||||
msgid "failed to create stream from socket: %s\n"
|
||||
@ -742,8 +742,8 @@ msgstr "请求使用密钥%%0A %s%%0A %s%%0A您想要允许这一请求吗?"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr ""
|
||||
"您真的想要删除这个被以下的 keygrip 所标识的密钥吗 %%0A %s%%0A %%C%%0A?"
|
||||
|
||||
@ -1774,14 +1774,14 @@ msgstr "由于在 S2K 模式,不能使用一个对称的 ESK 封包\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "使用加密 %s.%s\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "‘%s’已被压缩\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "警告:‘%s’是一个空文件\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "‘%s’已被压缩\n"
|
||||
|
||||
#, c-format
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
msgstr "摘要算法‘%s’不能在 %s 模式下使用\n"
|
||||
@ -8666,6 +8666,9 @@ msgstr "储存一个证书到数据对象"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr "储存私钥到数据对象"
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr "Yubikey 管理命令"
|
||||
|
||||
|
15
po/zh_TW.po
15
po/zh_TW.po
@ -783,8 +783,8 @@ msgstr ""
|
||||
#, fuzzy, c-format
|
||||
#| msgid "Do you really want to delete the selected keys? (y/N) "
|
||||
msgid ""
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A %%C"
|
||||
"%%0A?"
|
||||
"Do you really want to delete the key identified by keygrip%%0A %s%%0A "
|
||||
"%%C%%0A?"
|
||||
msgstr "你真的想要刪除所選的金鑰嗎? (y/N) "
|
||||
|
||||
msgid "Delete key"
|
||||
@ -1868,14 +1868,14 @@ msgstr "因處於 S2K 模式下而無法使用對稱式 ESK 封包\n"
|
||||
msgid "using cipher %s.%s\n"
|
||||
msgstr "正在使用 %s 編密法\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' 已經被壓縮了\n"
|
||||
|
||||
#, c-format
|
||||
msgid "WARNING: '%s' is an empty file\n"
|
||||
msgstr "警告: '%s' 是個空檔案\n"
|
||||
|
||||
#, c-format
|
||||
msgid "'%s' already compressed\n"
|
||||
msgstr "'%s' 已經被壓縮了\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#| msgid "you may not use digest algorithm '%s' while in %s mode\n"
|
||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||
@ -9048,6 +9048,9 @@ msgstr "加入憑證至快取"
|
||||
msgid "store a private key to a data object"
|
||||
msgstr ""
|
||||
|
||||
msgid "run various checks on the keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "Yubikey management commands"
|
||||
msgstr ""
|
||||
|
||||
|
@ -56,8 +56,8 @@ typedef enum
|
||||
CARDTYPE_GENERIC = 0,
|
||||
CARDTYPE_GNUK,
|
||||
CARDTYPE_YUBIKEY,
|
||||
CARDTYPE_ZEITCONTROL
|
||||
|
||||
CARDTYPE_ZEITCONTROL,
|
||||
CARDTYPE_SCE7 /* G+D SmartCafe Expert 7.0 */
|
||||
} cardtype_t;
|
||||
|
||||
/* List of supported card applications. The source code for each
|
||||
|
151
scd/app-p15.c
151
scd/app-p15.c
@ -91,7 +91,8 @@ typedef enum
|
||||
CARD_PRODUCT_DTRUST3, /* D-Trust GmbH (bundesdruckerei.de) */
|
||||
CARD_PRODUCT_DTRUST4,
|
||||
CARD_PRODUCT_GENUA, /* GeNUA mbH */
|
||||
CARD_PRODUCT_NEXUS /* Technology Nexus */
|
||||
CARD_PRODUCT_NEXUS, /* Technology Nexus */
|
||||
CARD_PRODUCT_CVISION /* Cryptovision GmbH */
|
||||
}
|
||||
card_product_t;
|
||||
|
||||
@ -143,6 +144,8 @@ static struct
|
||||
#define IS_CARDOS_5(a) ((a)->app_local->card_type == CARD_TYPE_CARDOS_50 \
|
||||
|| (a)->app_local->card_type == CARD_TYPE_CARDOS_53 \
|
||||
|| (a)->app_local->card_type == CARD_TYPE_CARDOS_54)
|
||||
#define IS_STARCOS_3(a) ((a)->app_local->card_type == CARD_TYPE_STARCOS_32)
|
||||
|
||||
|
||||
/* The default PKCS-15 home DF */
|
||||
#define DEFAULT_HOME_DF 0x5015
|
||||
@ -532,8 +535,6 @@ struct app_local_s
|
||||
/*** Local prototypes. ***/
|
||||
static gpg_error_t select_ef_by_path (app_t app, const unsigned short *path,
|
||||
size_t pathlen);
|
||||
static gpg_error_t select_df_by_path (app_t app, const unsigned short *path,
|
||||
size_t pathlen);
|
||||
static gpg_error_t keygrip_from_prkdf (app_t app, prkdf_object_t prkdf);
|
||||
static gpg_error_t readcert_by_cdf (app_t app, cdf_object_t cdf,
|
||||
unsigned char **r_cert, size_t *r_certlen);
|
||||
@ -571,6 +572,7 @@ cardproduct2str (card_product_t cardproduct)
|
||||
case CARD_PRODUCT_DTRUST4: return "D-Trust 4.1/4.4";
|
||||
case CARD_PRODUCT_GENUA: return "GeNUA";
|
||||
case CARD_PRODUCT_NEXUS: return "Nexus";
|
||||
case CARD_PRODUCT_CVISION: return "Cryptovison";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@ -803,7 +805,7 @@ select_by_path (app_t app, const unsigned short *path, size_t pathlen,
|
||||
log_debug ("%s: path=", __func__);
|
||||
for (j=0; j < pathlen; j++)
|
||||
log_printf ("%s%04hX", j? "/":"", path[j]);
|
||||
log_printf ("%s\n",expect_df?" (DF requested)":"");
|
||||
log_printf ("%s", expect_df?" (DF requested)":"");
|
||||
log_printf ("%s\n",app->app_local->direct_path_selection?" (direct)":"");
|
||||
}
|
||||
|
||||
@ -867,11 +869,13 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* Currently not used. */
|
||||
static gpg_error_t
|
||||
select_df_by_path (app_t app, const unsigned short *path, size_t pathlen)
|
||||
{
|
||||
return select_by_path (app, path, pathlen, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Parse a cert Id string (or a key Id string) and return the binary
|
||||
@ -3611,6 +3615,7 @@ read_p15_info (app_t app)
|
||||
gpg_error_t err;
|
||||
prkdf_object_t prkdf;
|
||||
unsigned int flag;
|
||||
const char *manu;
|
||||
|
||||
err = read_ef_tokeninfo (app);
|
||||
if (err)
|
||||
@ -3631,18 +3636,22 @@ read_p15_info (app_t app)
|
||||
release_lists (app);
|
||||
|
||||
/* Set a product type from the manufacturer_id. */
|
||||
if (IS_CARDOS_5 (app) && app->app_local->manufacturer_id)
|
||||
{
|
||||
const char *manu = app->app_local->manufacturer_id;
|
||||
|
||||
if (app->app_local->card_product)
|
||||
if (!(manu = app->app_local->manufacturer_id) || !*manu)
|
||||
; /* No manufacturer_id. */
|
||||
else if (app->app_local->card_product)
|
||||
; /* Already set. */
|
||||
else if (!ascii_strcasecmp (manu, "GeNUA mbH"))
|
||||
else if (IS_CARDOS_5 (app))
|
||||
{
|
||||
if (!ascii_strcasecmp (manu, "GeNUA mbH"))
|
||||
app->app_local->card_product = CARD_PRODUCT_GENUA;
|
||||
else if (!ascii_strcasecmp (manu, "Technology Nexus"))
|
||||
app->app_local->card_product = CARD_PRODUCT_NEXUS;
|
||||
}
|
||||
|
||||
else if (app->app_local->card_type == CARD_TYPE_STARCOS_32)
|
||||
{
|
||||
if (strstr (manu, "cryptovision"))
|
||||
app->app_local->card_product = CARD_PRODUCT_CVISION;
|
||||
}
|
||||
|
||||
/* Read the ODF so that we know the location of all directory
|
||||
files. */
|
||||
@ -5053,11 +5062,18 @@ prepare_verify_pin (app_t app, const char *keyref,
|
||||
log_error ("p15: error selecting D-TRUST's AID for key %s: %s\n",
|
||||
keyref, gpg_strerror (err));
|
||||
}
|
||||
else if (prkdf && app->app_local->card_type == CARD_TYPE_STARCOS_32)
|
||||
else if (app->app_local->card_product == CARD_PRODUCT_CVISION)
|
||||
{
|
||||
err = select_df_by_path (app, prkdf->path, prkdf->pathlen);
|
||||
/* According to our protocol analysis we need to select the
|
||||
* PKCS#15 AID here. The traces actually show that this is done
|
||||
* two times but that looks more like a bug. Before that the
|
||||
* master file needs to be selected. */
|
||||
err = iso7816_select_mf (app_get_slot (app));
|
||||
if (!err)
|
||||
err = iso7816_select_application (app_get_slot (app),
|
||||
pkcs15_aid, sizeof pkcs15_aid, 0);
|
||||
if (err)
|
||||
log_error ("p15: error selecting file for key %s: %s\n",
|
||||
log_error ("p15: error selecting PKCS#15 AID for key %s: %s\n",
|
||||
keyref, gpg_strerror (err));
|
||||
}
|
||||
else if (prkdf)
|
||||
@ -5497,6 +5513,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
unsigned char oidbuf[64];
|
||||
size_t oidbuflen;
|
||||
size_t n;
|
||||
int i;
|
||||
unsigned char *indata_buffer = NULL; /* Malloced helper. */
|
||||
|
||||
(void)ctrl;
|
||||
@ -5594,7 +5611,6 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
{
|
||||
unsigned int framelen;
|
||||
unsigned char *frame;
|
||||
int i;
|
||||
|
||||
framelen = (prkdf->keynbits+7) / 8;
|
||||
if (!framelen)
|
||||
@ -5669,6 +5685,23 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
memcpy (frame, indata, indatalen);
|
||||
framelen = indatalen;
|
||||
}
|
||||
else if (hashalgo && IS_STARCOS_3 (app)
|
||||
&& app->app_local->card_product != CARD_PRODUCT_CVISION)
|
||||
{
|
||||
/* For Starcos we need the plain hash w/o the prefix. */
|
||||
/* Note: This has never been tested because the cvision
|
||||
* sample cards seem not to work this way. */
|
||||
if (indatalen != oidbuflen + digestlen
|
||||
|| memcmp (indata, oidbuf, oidbuflen))
|
||||
{
|
||||
log_error ("p15: non-matching input data for Starcos:"
|
||||
" hash=%d len=%zu\n", hashalgo, indatalen);
|
||||
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||
goto leave;
|
||||
}
|
||||
framelen = indatalen - oidbuflen;
|
||||
memcpy (frame, (const char*)indata + oidbuflen, framelen);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = 0;
|
||||
@ -5758,7 +5791,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
else
|
||||
{
|
||||
/* The D-TRUST Card 4.x doesn't support setting a security
|
||||
* environment, at least as specified in the specs. Insted a
|
||||
* environment, at least as specified in the specs. Instead a
|
||||
* predefined security environment has to be loaded depending on the
|
||||
* cipher and message digest used. The spec states SE-ID 0x25 for
|
||||
* SHA256, 0x26 for SHA384 and 0x27 for SHA512, when using PKCS#1
|
||||
@ -5772,6 +5805,61 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
0xf3, 0x25, NULL, 0);
|
||||
}
|
||||
}
|
||||
else if (app->app_local->card_product == CARD_PRODUCT_CVISION)
|
||||
{
|
||||
/* I can't make the Starcos 3.2 work the correct way, so let's
|
||||
* make them work in the same way the cryptovision product seems
|
||||
* to do it: Use the plain RSA decryption instead. */
|
||||
unsigned char mse[9];
|
||||
|
||||
i = 0;
|
||||
mse[i++] = 0x84; /* Key reference. */
|
||||
mse[i++] = 1;
|
||||
mse[i++] = prkdf->key_reference;
|
||||
mse[i++] = 0x89; /* Algorithm reference (BCD encoded). */
|
||||
mse[i++] = 2;
|
||||
mse[i++] = 0x11; /* RSA no padding (1 1 3 0). */
|
||||
mse[i++] = 0x30;
|
||||
log_assert (i <= DIM(mse));
|
||||
err = iso7816_manage_security_env (app_get_slot (app), 0x41, 0xB8,
|
||||
mse, i);
|
||||
}
|
||||
else if (prkdf->key_reference_valid && IS_STARCOS_3 (app))
|
||||
{
|
||||
unsigned char mse[9];
|
||||
|
||||
i = 0;
|
||||
if (prkdf->is_ecc)
|
||||
{
|
||||
log_info ("Note: ECC is not yet implemented for Starcos 3 cards\n");
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = 0;
|
||||
mse[i++] = 0x84; /* Key reference. */
|
||||
mse[i++] = 1;
|
||||
mse[i++] = prkdf->key_reference;
|
||||
mse[i++] = 0x89; /* Algorithm reference (BCD encoded). */
|
||||
mse[i++] = 3;
|
||||
mse[i++] = 0x13; /* RSA PKCS#1 (standard) (1 3 2 3). */
|
||||
mse[i++] = 0x23;
|
||||
switch (hashalgo)
|
||||
{
|
||||
case GCRY_MD_SHA1: mse[i++] = 0x10; break;
|
||||
case GCRY_MD_RMD160: mse[i++] = 0x20; break;
|
||||
case GCRY_MD_SHA256: mse[i++] = 0x30; break;
|
||||
case GCRY_MD_SHA384: mse[i++] = 0x40; break;
|
||||
case GCRY_MD_SHA512: mse[i++] = 0x50; break;
|
||||
case GCRY_MD_SHA224: mse[i++] = 0x60; break;
|
||||
default: err = gpg_error (GPG_ERR_DIGEST_ALGO); break;
|
||||
}
|
||||
log_assert (i <= DIM(mse));
|
||||
if (!err)
|
||||
err = iso7816_manage_security_env (app_get_slot (app), 0x41, 0xB6,
|
||||
mse, i);
|
||||
}
|
||||
}
|
||||
else if (prkdf->key_reference_valid)
|
||||
{
|
||||
unsigned char mse[3];
|
||||
@ -5801,6 +5889,11 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
le_value = 0;
|
||||
}
|
||||
|
||||
if (app->app_local->card_product == CARD_PRODUCT_CVISION)
|
||||
err = iso7816_decipher (app_get_slot (app),
|
||||
exmode, indata, indatalen,
|
||||
le_value, 0, outdata, outdatalen);
|
||||
else
|
||||
err = iso7816_compute_ds (app_get_slot (app),
|
||||
exmode, indata, indatalen,
|
||||
le_value, outdata, outdatalen);
|
||||
@ -5862,6 +5955,7 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
|
||||
prkdf_object_t prkdf; /* The private key object. */
|
||||
aodf_object_t aodf; /* The associated authentication object. */
|
||||
int exmode, le_value, padind;
|
||||
int i;
|
||||
|
||||
(void)ctrl;
|
||||
(void)r_info;
|
||||
@ -5960,10 +6054,33 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
|
||||
0xF3, 0x31, NULL, 0);
|
||||
}
|
||||
}
|
||||
else if (prkdf->key_reference_valid && IS_STARCOS_3 (app))
|
||||
{
|
||||
unsigned char mse[9];
|
||||
|
||||
i = 0;
|
||||
if (prkdf->is_ecc)
|
||||
{
|
||||
log_info ("Note: ECC is not yet implemented for Starcos 3 cards\n");
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
|
||||
}
|
||||
else
|
||||
{
|
||||
mse[i++] = 0x84; /* Key reference. */
|
||||
mse[i++] = 1;
|
||||
mse[i++] = prkdf->key_reference;
|
||||
mse[i++] = 0x89; /* Algorithm reference (BCD encoded). */
|
||||
mse[i++] = 2;
|
||||
mse[i++] = 0x11; /* RSA no padding (1 1 3 0). */
|
||||
mse[i++] = 0x30;
|
||||
log_assert (i <= DIM(mse));
|
||||
err = iso7816_manage_security_env (app_get_slot (app), 0x41, 0xB8,
|
||||
mse, i);
|
||||
}
|
||||
}
|
||||
else if (prkdf->key_reference_valid)
|
||||
{
|
||||
unsigned char mse[9];
|
||||
int i;
|
||||
|
||||
/* Note: This works with CardOS but the D-Trust card has the
|
||||
* problem that the next created signature would be broken. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* app-piv.c - The OpenPGP card application.
|
||||
* Copyright (C) 2019, 2020 g10 Code GmbH
|
||||
* Copyright (C) 2019, 2020, 2024 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -3642,6 +3642,7 @@ app_select_piv (app_t app)
|
||||
size_t aptlen;
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
void *relptr1 = NULL;
|
||||
|
||||
/* Note that we select using the AID without the 2 octet version
|
||||
* number. This allows for better reporting of future specs. We
|
||||
@ -3667,7 +3668,21 @@ app_select_piv (app_t app)
|
||||
|
||||
s = find_tlv (apt, aptlen, 0x4F, &n);
|
||||
/* Some cards (new Yubikey) return only the PIX, while others
|
||||
* (old Yubikey, PivApplet) return the RID+PIX. */
|
||||
* (old Yubikey, PivApplet) return the RID+PIX.
|
||||
* Sample APTs:
|
||||
* Yubikey 5.4.3: 6111 4f06 000010000100 7907 4f05 a000000308
|
||||
* SCE7.0-G-F-P : 610f 4f06 001000010000 7905 a000000308
|
||||
*/
|
||||
if (app->card->cardtype == CARDTYPE_SCE7
|
||||
&& s && apt && aptlen == 17
|
||||
&& !memcmp (apt, ("\x61\x0f\x4f\x06\x00\x10\x00\x01"
|
||||
"\x00\x00\x79\x05\xa0\x00\x00\x03\x08"), aptlen))
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("piv: assuming G&D SCE7.0-G-F-P\n");
|
||||
app->appversion = 0x0100; /* Let's assume this. */
|
||||
goto apt_checked;
|
||||
}
|
||||
if (!s || !((n == 6 && !memcmp (s, piv_aid+5, 4))
|
||||
|| (n == 11 && !memcmp (s, piv_aid, 9))))
|
||||
{
|
||||
@ -3702,6 +3717,7 @@ app_select_piv (app_t app)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
apt_checked:
|
||||
app->app_local = xtrycalloc (1, sizeof *app->app_local);
|
||||
if (!app->app_local)
|
||||
{
|
||||
@ -3712,6 +3728,41 @@ app_select_piv (app_t app)
|
||||
if (app->card->cardtype == CARDTYPE_YUBIKEY)
|
||||
app->app_local->flags.yubikey = 1;
|
||||
|
||||
/* If we don't have a s/n construct it from the CHUID. */
|
||||
if (!APP_CARD(app)->serialno)
|
||||
{
|
||||
unsigned char *chuid;
|
||||
size_t chuidlen;
|
||||
|
||||
relptr1 = get_one_do (app, 0x5FC102, &chuid, &chuidlen, NULL);
|
||||
if (!relptr1)
|
||||
log_error ("piv: CHUID not found\n");
|
||||
else
|
||||
{
|
||||
s = find_tlv (chuid, chuidlen, 0x34, &n);
|
||||
if (!s || n != 16)
|
||||
{
|
||||
log_error ("piv: Card UUID %s in CHUID\n",
|
||||
s? "invalid":"missing");
|
||||
if (opt.debug && s)
|
||||
log_printhex (s, n, "got");
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_CARD(app)->serialno = xtrymalloc (n);
|
||||
if (!APP_CARD(app)->serialno)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
memcpy (APP_CARD(app)->serialno, s, n);
|
||||
APP_CARD(app)->serialnolen = n;
|
||||
err = app_munge_serialno (APP_CARD(app));
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Parse the optional and conditional DOs in the APT. */
|
||||
|
||||
@ -3739,6 +3790,7 @@ app_select_piv (app_t app)
|
||||
|
||||
|
||||
leave:
|
||||
xfree (relptr1);
|
||||
xfree (apt);
|
||||
if (err)
|
||||
do_deinit (app);
|
||||
|
53
scd/app.c
53
scd/app.c
@ -112,6 +112,7 @@ strcardtype (cardtype_t t)
|
||||
case CARDTYPE_GNUK: return "gnuk";
|
||||
case CARDTYPE_YUBIKEY: return "yubikey";
|
||||
case CARDTYPE_ZEITCONTROL: return "zeitcontrol";
|
||||
case CARDTYPE_SCE7: return "smartcafe";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
@ -549,6 +550,51 @@ card_reset (card_t card)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Return the card type from (ATR,ATRLEN) or CARDTYPE_GENERIC in case
|
||||
* of error or if the ATR was not found. If ATR is NULL, SLOT is used
|
||||
* to retrieve the ATR from the reader. */
|
||||
static cardtype_t
|
||||
atr_to_cardtype (int slot, const unsigned char *atr, size_t atrlen)
|
||||
{
|
||||
#define X(a) ((unsigned char const *)(a))
|
||||
static struct
|
||||
{
|
||||
size_t atrlen;
|
||||
unsigned char const *atr;
|
||||
cardtype_t type;
|
||||
} atrlist[] = {
|
||||
{ 19, X("\x3b\xf9\x96\x00\x00\x80\x31\xfe"
|
||||
"\x45\x53\x43\x45\x37\x20\x0f\x00\x20\x46\x4e"),
|
||||
CARDTYPE_SCE7 },
|
||||
{ 0 }
|
||||
};
|
||||
#undef X
|
||||
unsigned char *atrbuf = NULL;
|
||||
cardtype_t cardtype = 0;
|
||||
int i;
|
||||
|
||||
if (atr)
|
||||
{
|
||||
atrbuf = apdu_get_atr (slot, &atrlen);
|
||||
if (!atrbuf)
|
||||
return 0;
|
||||
atr = atrbuf;
|
||||
}
|
||||
|
||||
for (i=0; atrlist[i].atrlen; i++)
|
||||
if (atrlist[i].atrlen == atrlen
|
||||
&& !memcmp (atrlist[i].atr, atr, atrlen))
|
||||
{
|
||||
cardtype = atrlist[i].type;
|
||||
break;
|
||||
}
|
||||
xfree (atrbuf);
|
||||
return cardtype;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
app_new_register (int slot, ctrl_t ctrl, const char *name,
|
||||
int periodical_check_needed)
|
||||
@ -666,13 +712,16 @@ app_new_register (int slot, ctrl_t ctrl, const char *name,
|
||||
}
|
||||
xfree (buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
card->cardtype = atr_to_cardtype (slot, NULL, 0);
|
||||
}
|
||||
else /* Got 3F00 */
|
||||
{
|
||||
unsigned char *atr;
|
||||
size_t atrlen;
|
||||
|
||||
/* This is heuristics to identify different implementations. */
|
||||
/* FIXME: The first two checks are pretty OpenPGP card specific. */
|
||||
atr = apdu_get_atr (slot, &atrlen);
|
||||
if (atr)
|
||||
{
|
||||
@ -680,6 +729,8 @@ app_new_register (int slot, ctrl_t ctrl, const char *name,
|
||||
card->cardtype = CARDTYPE_GNUK;
|
||||
else if (atrlen == 21 && atr[7] == 0x75)
|
||||
card->cardtype = CARDTYPE_ZEITCONTROL;
|
||||
else
|
||||
card->cardtype = atr_to_cardtype (slot, atr, atrlen);
|
||||
xfree (atr);
|
||||
}
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ ecdh_encrypt (DEK dek, gcry_sexp_t s_pkey, gcry_sexp_t *r_encval)
|
||||
encr_algo_str = "1.3.132.1.11.2";
|
||||
wrap_algo_str = "2.16.840.1.101.3.4.1.25";
|
||||
hash_algo = GCRY_MD_SHA384;
|
||||
cipher_algo = GCRY_CIPHER_AES256;
|
||||
cipher_algo = GCRY_CIPHER_AES192;
|
||||
keylen = 24;
|
||||
}
|
||||
else
|
||||
|
157
sm/import.c
157
sm/import.c
@ -681,6 +681,85 @@ store_cert_cb (void *opaque,
|
||||
}
|
||||
|
||||
|
||||
/* Helper for parse_p12. */
|
||||
static gpg_error_t
|
||||
p12_to_skey (gcry_mpi_t *kparms, const char *curve, gcry_sexp_t *r_skey)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
struct rsa_secret_key_s sk;
|
||||
gcry_ctx_t ecctx = NULL;
|
||||
|
||||
if (curve)
|
||||
{
|
||||
/* log_debug ("curve: %s\n", curve); */
|
||||
/* gcry_log_debugmpi ("MPI[0]", kparms[0]); */
|
||||
|
||||
/* We need to get the public key. */
|
||||
err = gcry_mpi_ec_new (&ecctx, NULL, curve);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error creating context for curve '%s': %s\n",
|
||||
curve, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
err = gcry_mpi_ec_set_mpi ("d", kparms[0], ecctx);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error setting 'd' into context of curve '%s': %s\n",
|
||||
curve, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
kparms[1] = gcry_mpi_ec_get_mpi ("q", ecctx, 1);
|
||||
if (!kparms[1])
|
||||
{
|
||||
log_error ("error computing 'q' from 'd' for curve '%s'\n", curve);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = gcry_sexp_build (r_skey, NULL,
|
||||
"(private-key(ecc(curve %s)(q%m)(d%m)))",
|
||||
curve, kparms[1], kparms[0], NULL);
|
||||
}
|
||||
else /* RSA */
|
||||
{
|
||||
/* print_mpi (" n", kparms[0]); */
|
||||
/* print_mpi (" e", kparms[1]); */
|
||||
/* print_mpi (" d", kparms[2]); */
|
||||
/* print_mpi (" p", kparms[3]); */
|
||||
/* print_mpi (" q", kparms[4]); */
|
||||
/* print_mpi ("dmp1", kparms[5]); */
|
||||
/* print_mpi ("dmq1", kparms[6]); */
|
||||
/* print_mpi (" u", kparms[7]); */
|
||||
|
||||
sk.n = kparms[0];
|
||||
sk.e = kparms[1];
|
||||
sk.d = kparms[2];
|
||||
sk.q = kparms[3];
|
||||
sk.p = kparms[4];
|
||||
sk.u = kparms[7];
|
||||
err = rsa_key_check (&sk);
|
||||
if (err)
|
||||
goto leave;
|
||||
/* print_mpi (" n", sk.n); */
|
||||
/* print_mpi (" e", sk.e); */
|
||||
/* print_mpi (" d", sk.d); */
|
||||
/* print_mpi (" p", sk.p); */
|
||||
/* print_mpi (" q", sk.q); */
|
||||
/* print_mpi (" u", sk.u); */
|
||||
|
||||
/* Create an S-expression from the parameters. */
|
||||
err = gcry_sexp_build (r_skey, NULL,
|
||||
"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
|
||||
sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, NULL);
|
||||
}
|
||||
|
||||
leave:
|
||||
gcry_ctx_release (ecctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Assume that the reader is at a pkcs#12 message and try to import
|
||||
certificates from that stupid format. We will transfer secret
|
||||
keys to the agent. */
|
||||
@ -695,7 +774,6 @@ parse_p12 (ctrl_t ctrl, ksba_reader_t reader, struct stats_s *stats)
|
||||
size_t p12buflen;
|
||||
size_t p12bufoff;
|
||||
gcry_mpi_t *kparms = NULL;
|
||||
struct rsa_secret_key_s sk;
|
||||
char *passphrase = NULL;
|
||||
unsigned char *key = NULL;
|
||||
size_t keylen;
|
||||
@ -781,82 +859,9 @@ parse_p12 (ctrl_t ctrl, ksba_reader_t reader, struct stats_s *stats)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (curve)
|
||||
{
|
||||
gcry_ctx_t ecctx = NULL;
|
||||
|
||||
/* log_debug ("curve: %s\n", curve); */
|
||||
/* gcry_log_debugmpi ("MPI[0]", kparms[0]); */
|
||||
|
||||
/* We need to get the public key. */
|
||||
err = gcry_mpi_ec_new (&ecctx, NULL, curve);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error creating context for curve '%s': %s\n",
|
||||
curve, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
err = gcry_mpi_ec_set_mpi ("d", kparms[0], ecctx);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error setting 'd' into context of curve '%s': %s\n",
|
||||
curve, gpg_strerror (err));
|
||||
gcry_ctx_release (ecctx);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
kparms[1] = gcry_mpi_ec_get_mpi ("q", ecctx, 1);
|
||||
if (!kparms[1])
|
||||
{
|
||||
log_error ("error computing 'q' from 'd' for curve '%s'\n", curve);
|
||||
gcry_ctx_release (ecctx);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
gcry_ctx_release (ecctx);
|
||||
|
||||
err = gcry_sexp_build (&s_key, NULL,
|
||||
"(private-key(ecc(curve %s)(q%m)(d%m)))",
|
||||
curve, kparms[1], kparms[0], NULL);
|
||||
}
|
||||
else /* RSA */
|
||||
{
|
||||
/* print_mpi (" n", kparms[0]); */
|
||||
/* print_mpi (" e", kparms[1]); */
|
||||
/* print_mpi (" d", kparms[2]); */
|
||||
/* print_mpi (" p", kparms[3]); */
|
||||
/* print_mpi (" q", kparms[4]); */
|
||||
/* print_mpi ("dmp1", kparms[5]); */
|
||||
/* print_mpi ("dmq1", kparms[6]); */
|
||||
/* print_mpi (" u", kparms[7]); */
|
||||
|
||||
sk.n = kparms[0];
|
||||
sk.e = kparms[1];
|
||||
sk.d = kparms[2];
|
||||
sk.q = kparms[3];
|
||||
sk.p = kparms[4];
|
||||
sk.u = kparms[7];
|
||||
err = rsa_key_check (&sk);
|
||||
if (err)
|
||||
goto leave;
|
||||
/* print_mpi (" n", sk.n); */
|
||||
/* print_mpi (" e", sk.e); */
|
||||
/* print_mpi (" d", sk.d); */
|
||||
/* print_mpi (" p", sk.p); */
|
||||
/* print_mpi (" q", sk.q); */
|
||||
/* print_mpi (" u", sk.u); */
|
||||
|
||||
/* Create an S-expression from the parameters. */
|
||||
err = gcry_sexp_build (&s_key, NULL,
|
||||
"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
|
||||
sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, NULL);
|
||||
}
|
||||
|
||||
/* The next is very ugly - we really should not rely on our
|
||||
* knowledge of p12_parse internals. */
|
||||
for (i=0; i < 8; i++)
|
||||
gcry_mpi_release (kparms[i]);
|
||||
gcry_free (kparms);
|
||||
err = p12_to_skey (kparms, curve, &s_key);
|
||||
p12_parse_free_kparms (kparms);
|
||||
kparms = NULL;
|
||||
if (err)
|
||||
{
|
||||
|
58
sm/minip12.c
58
sm/minip12.c
@ -168,6 +168,9 @@ struct p12_parse_ctx_s
|
||||
|
||||
/* The private key as an MPI array. */
|
||||
gcry_mpi_t *privatekey;
|
||||
|
||||
/* A second private key as an MPI array. */
|
||||
gcry_mpi_t *privatekey2;
|
||||
};
|
||||
|
||||
|
||||
@ -1248,6 +1251,7 @@ parse_shrouded_key_bag (struct p12_parse_ctx_s *ctx, tlv_parser_t tlv)
|
||||
int is_pbes2 = 0;
|
||||
int is_aes256 = 0;
|
||||
int digest_algo = GCRY_MD_SHA1;
|
||||
gcry_mpi_t *privatekey;
|
||||
|
||||
where = "shrouded_key_bag";
|
||||
if (opt_verbose)
|
||||
@ -1565,19 +1569,26 @@ parse_shrouded_key_bag (struct p12_parse_ctx_s *ctx, tlv_parser_t tlv)
|
||||
if (tlv_expect_sequence (tlv))
|
||||
goto bailout;
|
||||
|
||||
if (ctx->privatekey)
|
||||
if (ctx->privatekey2)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_DUP_VALUE);
|
||||
log_error ("a private key has already been received\n");
|
||||
log_error ("two private kesy have already been received\n");
|
||||
goto bailout;
|
||||
}
|
||||
ctx->privatekey = gcry_calloc (10, sizeof *ctx->privatekey);
|
||||
if (!ctx->privatekey)
|
||||
privatekey = gcry_calloc (10, sizeof *privatekey);
|
||||
if (!privatekey)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error allocating privatekey element array\n");
|
||||
goto bailout;
|
||||
}
|
||||
if (ctx->privatekey)
|
||||
{
|
||||
log_info ("a private key has already been received - reading second\n");
|
||||
ctx->privatekey2 = privatekey;
|
||||
}
|
||||
else
|
||||
ctx->privatekey = privatekey;
|
||||
|
||||
where = "shrouded_key_bag.reading.key-parameters";
|
||||
if (ctx->curve) /* ECC case. */
|
||||
@ -1600,7 +1611,7 @@ parse_shrouded_key_bag (struct p12_parse_ctx_s *ctx, tlv_parser_t tlv)
|
||||
goto bailout;
|
||||
if (opt_verbose > 1)
|
||||
log_printhex (data, datalen, "ecc q=");
|
||||
err = gcry_mpi_scan (ctx->privatekey, GCRYMPI_FMT_USG,
|
||||
err = gcry_mpi_scan (privatekey, GCRYMPI_FMT_USG,
|
||||
data, datalen, NULL);
|
||||
if (err)
|
||||
{
|
||||
@ -1623,7 +1634,7 @@ parse_shrouded_key_bag (struct p12_parse_ctx_s *ctx, tlv_parser_t tlv)
|
||||
}
|
||||
|
||||
err = tlv_expect_mpinteger (tlv, firstparam,
|
||||
ctx->privatekey+keyelem_count);
|
||||
privatekey+keyelem_count);
|
||||
if (firstparam && gpg_err_code (err) == GPG_ERR_FALSE)
|
||||
; /* Ignore the first value iff it is zero. */
|
||||
else if (err)
|
||||
@ -1918,6 +1929,7 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
|
||||
size_t oidlen;
|
||||
int intval;
|
||||
unsigned int startlevel;
|
||||
int i;
|
||||
|
||||
*r_badpass = 0;
|
||||
|
||||
@ -2037,6 +2049,15 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
|
||||
else
|
||||
gcry_free (ctx.curve);
|
||||
|
||||
/* We have no way yet to return the second private key. */
|
||||
if (ctx.privatekey2)
|
||||
{
|
||||
for (i=0; ctx.privatekey2[i]; i++)
|
||||
gcry_mpi_release (ctx.privatekey2[i]);
|
||||
gcry_free (ctx.privatekey2);
|
||||
ctx.privatekey2 = NULL;
|
||||
}
|
||||
|
||||
return ctx.privatekey;
|
||||
|
||||
bailout:
|
||||
@ -2050,13 +2071,18 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
|
||||
gpg_strerror (err));
|
||||
if (ctx.privatekey)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; ctx.privatekey[i]; i++)
|
||||
gcry_mpi_release (ctx.privatekey[i]);
|
||||
gcry_free (ctx.privatekey);
|
||||
ctx.privatekey = NULL;
|
||||
}
|
||||
if (ctx.privatekey2)
|
||||
{
|
||||
for (i=0; ctx.privatekey2[i]; i++)
|
||||
gcry_mpi_release (ctx.privatekey2[i]);
|
||||
gcry_free (ctx.privatekey2);
|
||||
ctx.privatekey2 = NULL;
|
||||
}
|
||||
tlv_parser_release (tlv);
|
||||
gcry_free (ctx.curve);
|
||||
if (r_curve)
|
||||
@ -2065,6 +2091,22 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
|
||||
}
|
||||
|
||||
|
||||
/* Free the parameters as returned by p12_parse. */
|
||||
void
|
||||
p12_parse_free_kparms (gcry_mpi_t *kparms)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (kparms)
|
||||
{
|
||||
for (i=0; i < 8; i++)
|
||||
gcry_mpi_release (kparms[i]);
|
||||
gcry_free (kparms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static size_t
|
||||
compute_tag_length (size_t n)
|
||||
|
@ -29,6 +29,7 @@ gcry_mpi_t *p12_parse (const unsigned char *buffer, size_t length,
|
||||
const char *pw,
|
||||
void (*certcb)(void*, const unsigned char*, size_t),
|
||||
void *certcbarg, int *r_badpass, char **r_curve);
|
||||
void p12_parse_free_kparms (gcry_mpi_t *kparms);
|
||||
|
||||
unsigned char *p12_build (gcry_mpi_t *kparms,
|
||||
const void *cert, size_t certlen,
|
||||
|
@ -580,13 +580,7 @@ run_one_test (const char *name, const char *desc, const char *pass,
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
int i;
|
||||
for (i=0; result[i]; i++)
|
||||
gcry_mpi_release (result[i]);
|
||||
gcry_free (result);
|
||||
}
|
||||
p12_parse_free_kparms (result);
|
||||
xfree (certstr);
|
||||
xfree (resulthash);
|
||||
xfree (curve);
|
||||
|
@ -737,7 +737,12 @@ gpgsm_verify (ctrl_t ctrl, estream_t in_fp, estream_t data_fp,
|
||||
char numbuf[50];
|
||||
sprintf (numbuf, "%d", rc );
|
||||
gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
|
||||
numbuf, NULL);
|
||||
numbuf,
|
||||
gpg_err_code (rc) == GPG_ERR_EPIPE?
|
||||
"-- (Broken pipe on input or output)":
|
||||
gpg_err_code (rc) == GPG_ERR_EOF?
|
||||
"-- (End of file)" : NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
@ -99,8 +99,11 @@ EXTRA_DIST = $(XTESTS) $(KEYS) $(CERTS) $(TEST_FILES) \
|
||||
samplekeys/opensc-test.p12 \
|
||||
samplekeys/t5793-openssl.pfx \
|
||||
samplekeys/t5793-test.pfx \
|
||||
samplekeys/t6752-ov-user-ff.p12 \
|
||||
samplekeys/edward.tester@demo.gnupg.com.p12 \
|
||||
samplekeys/nistp256-openssl-self-signed.p12 \
|
||||
samplekeys/credential_private_encrypted_AES256.p12 \
|
||||
samplekeys/credential_private_encrypted_3DES.p12 \
|
||||
samplemsgs/pwri-sample.cbc.p7m \
|
||||
samplemsgs/pwri-sample.cbc-2.p7m \
|
||||
samplemsgs/pwri-sample.gcm.p7m \
|
||||
|
@ -51,4 +51,16 @@ Pass: start
|
||||
Cert: 4753a910e0c8b4caa8663ca0e4273a884eb5397d
|
||||
Key: 93be89edd11214ab74280d988a665b6beef876c5
|
||||
|
||||
Name: credential_private_encrypted_AES256.p12
|
||||
Desc: AES256 encrypted P12 file from T6940
|
||||
Pass: qeFGds84/Sf0eKkJwcp6
|
||||
Cert: 20f65740b4a15bac6d6a299026756088f7604937,cbb4b26f93cfd9715ac9fa43440470df9395571b
|
||||
Key: 37eedaaf317edb69029eed79f69dd479fb10bf08
|
||||
|
||||
Name: credential_private_encrypted_3DES.p12
|
||||
Desc: 3DES encrypted P12 file from T6940
|
||||
Pass: qeFGds84/Sf0eKkJwcp6
|
||||
Cert: 20f65740b4a15bac6d6a299026756088f7604937,cbb4b26f93cfd9715ac9fa43440470df9395571b
|
||||
Key: 37eedaaf317edb69029eed79f69dd479fb10bf08
|
||||
|
||||
# eof #
|
||||
|
BIN
tests/cms/samplekeys/credential_private_encrypted_3DES.p12
Normal file
BIN
tests/cms/samplekeys/credential_private_encrypted_3DES.p12
Normal file
Binary file not shown.
BIN
tests/cms/samplekeys/credential_private_encrypted_AES256.p12
Normal file
BIN
tests/cms/samplekeys/credential_private_encrypted_AES256.p12
Normal file
Binary file not shown.
@ -1530,6 +1530,7 @@ scd_readkey (const char *keyrefstr, int create_shadow, gcry_sexp_t *r_result)
|
||||
unsigned char *buf;
|
||||
size_t len, buflen;
|
||||
|
||||
if (r_result)
|
||||
*r_result = NULL;
|
||||
err = start_agent (0);
|
||||
if (err)
|
||||
@ -1537,7 +1538,8 @@ scd_readkey (const char *keyrefstr, int create_shadow, gcry_sexp_t *r_result)
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
if (create_shadow)
|
||||
snprintf (line, DIM(line), "READKEY --card -- %s", keyrefstr);
|
||||
snprintf (line, DIM(line), "READKEY %s--card -- %s",
|
||||
r_result? "" : "--no-data ", keyrefstr);
|
||||
else
|
||||
snprintf (line, DIM(line), "SCD READKEY %s", keyrefstr);
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
@ -1553,7 +1555,7 @@ scd_readkey (const char *keyrefstr, int create_shadow, gcry_sexp_t *r_result)
|
||||
if (!buf)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
err = gcry_sexp_new (r_result, buf, buflen, 0);
|
||||
err = r_result ? gcry_sexp_new (r_result, buf, buflen, 0) : 0;
|
||||
xfree (buf);
|
||||
|
||||
return err;
|
||||
@ -1770,6 +1772,90 @@ agent_get_s2k_count (void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct havekey_status_parm_s
|
||||
{
|
||||
char *string;
|
||||
};
|
||||
|
||||
static gpg_error_t
|
||||
havekey_status_cb (void *opaque, const char *line)
|
||||
{
|
||||
struct havekey_status_parm_s *parm = opaque;
|
||||
const char *s;
|
||||
char *p;
|
||||
|
||||
if ((s = has_leading_keyword (line, "KEYFILEINFO")))
|
||||
{
|
||||
xfree (parm->string);
|
||||
parm->string = xtrystrdup (s);
|
||||
if (!parm->string)
|
||||
return gpg_error_from_syserror ();
|
||||
p = strchr (parm->string, ' ');
|
||||
if (p)
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run the HAVEKEY --info command and stores the retrieved string at
|
||||
* R_RESULT. Caller must free that string. If an error is returned
|
||||
* R_RESULT is set to NULL. */
|
||||
gpg_error_t
|
||||
scd_havekey_info (const unsigned char *grip, char **r_result)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct havekey_status_parm_s parm = {NULL};
|
||||
|
||||
*r_result = NULL;
|
||||
|
||||
err = start_agent (0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
snprintf (line, sizeof line, "HAVEKEY --info ");
|
||||
log_assert (ASSUAN_LINELENGTH > strlen(line) + 2*KEYGRIP_LEN + 10);
|
||||
bin2hex (grip, KEYGRIP_LEN, line+strlen(line));
|
||||
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL, NULL, NULL,
|
||||
havekey_status_cb, &parm);
|
||||
if (err)
|
||||
xfree (parm.string);
|
||||
else
|
||||
*r_result = parm.string;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Run the DELETE_KEY command. If FORCE is given the user will not be
|
||||
* asked for confirmation. */
|
||||
gpg_error_t
|
||||
scd_delete_key (const unsigned char *grip, int force)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm = {NULL};
|
||||
|
||||
err = start_agent (0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, sizeof line, "DELETE_KEY%s ", force?" --force":"");
|
||||
log_assert (ASSUAN_LINELENGTH > strlen(line) + 2*KEYGRIP_LEN + 10);
|
||||
bin2hex (grip, KEYGRIP_LEN, line+strlen(line));
|
||||
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL, default_inq_cb, &dfltparm, NULL, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Return a malloced string describing the statusword SW. On error
|
||||
* NULL is returned. */
|
||||
char *
|
||||
|
140
tools/gpg-card.c
140
tools/gpg-card.c
@ -582,12 +582,13 @@ print_shax_fpr (estream_t fp, const unsigned char *fpr, unsigned int fprlen)
|
||||
|
||||
/* Print the keygrip GRP. */
|
||||
static void
|
||||
print_keygrip (estream_t fp, const unsigned char *grp)
|
||||
print_keygrip (estream_t fp, const unsigned char *grp, int with_lf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < 20 ; i++, grp++)
|
||||
tty_fprintf (fp, "%02X", *grp);
|
||||
if (with_lf)
|
||||
tty_fprintf (fp, "\n");
|
||||
}
|
||||
|
||||
@ -700,7 +701,7 @@ list_one_kinfo (card_info_t info, key_info_t kinfo,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
print_keygrip (fp, kinfo->grip);
|
||||
print_keygrip (fp, kinfo->grip, 1);
|
||||
tty_fprintf (fp, " keyref .....: %s", kinfo->keyref);
|
||||
if (kinfo->usage)
|
||||
{
|
||||
@ -1376,6 +1377,137 @@ cmd_list (card_info_t info, char *argstr)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The CHECKKEYS command. */
|
||||
static gpg_error_t
|
||||
cmd_checkkeys (card_info_t callerinfo, char *argstr)
|
||||
{
|
||||
gpg_error_t err;
|
||||
estream_t fp = opt.interactive? NULL : es_stdout;
|
||||
strlist_t cards = NULL;
|
||||
strlist_t sl;
|
||||
int opt_ondisk;
|
||||
int opt_delete_clear;
|
||||
int opt_delete_protected;
|
||||
int delete_count = 0;
|
||||
struct card_info_s info_buffer = { 0 };
|
||||
card_info_t info = &info_buffer;
|
||||
key_info_t kinfo;
|
||||
|
||||
|
||||
if (!callerinfo)
|
||||
return print_help
|
||||
("CHECKKEYS [--ondisk] [--delete-clear-copy] [--delete-protected-copy]"
|
||||
"\n\n"
|
||||
"Print a list of keys on all inserted cards. With --ondisk only\n"
|
||||
"keys are listed which also have a copy on disk. Missing shadow\n"
|
||||
"keys are created. With --delete-clear-copy, copies of keys also\n"
|
||||
"stored on disk without any protection will be deleted.\n"
|
||||
, 0);
|
||||
|
||||
|
||||
opt_ondisk = has_leading_option (argstr, "--ondisk");
|
||||
opt_delete_clear = has_leading_option (argstr, "--delete-clear-copy");
|
||||
opt_delete_protected = has_leading_option (argstr, "--delete-protected-copy");
|
||||
argstr = skip_options (argstr);
|
||||
|
||||
if (*argstr)
|
||||
{
|
||||
/* No args expected */
|
||||
err = gpg_error (GPG_ERR_INV_ARG);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!callerinfo->serialno)
|
||||
{
|
||||
/* This is probably the first call We need to send a SERIALNO
|
||||
* command to scdaemon so that our session knows all cards. */
|
||||
err = scd_serialno (NULL, NULL);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Get the list of all cards. */
|
||||
err = scd_cardlist (&cards);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Loop over all cards. We use our own info buffer here. */
|
||||
for (sl = cards; sl; sl = sl->next)
|
||||
{
|
||||
err = scd_switchcard (sl->d);
|
||||
if (err)
|
||||
{
|
||||
log_error ("Error switching to card %s: %s\n",
|
||||
sl->d, gpg_strerror (err));
|
||||
continue;
|
||||
}
|
||||
release_card_info (info);
|
||||
err = scd_learn (info, 0);
|
||||
if (err)
|
||||
{
|
||||
log_error ("Error getting infos from card %s: %s\n",
|
||||
sl->d, gpg_strerror (err));
|
||||
continue;
|
||||
}
|
||||
|
||||
for (kinfo = info->kinfo; kinfo; kinfo = kinfo->next)
|
||||
{
|
||||
char *infostr;
|
||||
|
||||
err = scd_havekey_info (kinfo->grip, &infostr);
|
||||
if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
|
||||
{
|
||||
/* Create a shadow key and try again. */
|
||||
scd_readkey (kinfo->keyref, 1, NULL);
|
||||
err = scd_havekey_info (kinfo->grip, &infostr);
|
||||
}
|
||||
if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
|
||||
log_error ("Error getting infos for a key: %s\n",
|
||||
gpg_strerror (err));
|
||||
|
||||
if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
|
||||
; /* does not make sense to show this. */
|
||||
else if (opt_ondisk && infostr && !strcmp (infostr, "shadowed"))
|
||||
; /* Don't print this one. */
|
||||
else
|
||||
{
|
||||
tty_fprintf (fp, "%s %s ",
|
||||
nullnone (info->serialno),
|
||||
app_type_string (info->apptype));
|
||||
print_keygrip (fp, kinfo->grip, 0);
|
||||
tty_fprintf (fp, " %s %s\n",
|
||||
kinfo->keyref, infostr? infostr: "error");
|
||||
}
|
||||
if (infostr
|
||||
&& ((opt_delete_clear && !strcmp (infostr, "clear"))
|
||||
|| (opt_delete_protected && !strcmp (infostr, "protected"))))
|
||||
{
|
||||
err = scd_delete_key (kinfo->grip, 0);
|
||||
if (err)
|
||||
log_error ("Error deleting a key copy: %s\n",
|
||||
gpg_strerror (err));
|
||||
else
|
||||
delete_count++;
|
||||
}
|
||||
xfree (infostr);
|
||||
}
|
||||
}
|
||||
es_fflush (es_stdout);
|
||||
if (delete_count)
|
||||
log_info ("Number of deleted key copies: %d\n", delete_count);
|
||||
|
||||
err = 0;
|
||||
|
||||
leave:
|
||||
release_card_info (info);
|
||||
free_strlist (cards);
|
||||
/* Better reset to the original card. */
|
||||
scd_learn (callerinfo, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The VERIFY command. */
|
||||
static gpg_error_t
|
||||
@ -3728,6 +3860,7 @@ enum cmdids
|
||||
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
|
||||
cmdREADCERT, cmdWRITEKEY, cmdUNBLOCK, cmdFACTRST, cmdKDFSETUP,
|
||||
cmdUIF, cmdAUTH, cmdYUBIKEY, cmdAPDU, cmdGPG, cmdGPGSM, cmdHISTORY,
|
||||
cmdCHECKKEYS,
|
||||
cmdINVCMD
|
||||
};
|
||||
|
||||
@ -3767,6 +3900,7 @@ static struct
|
||||
{ "readcert", cmdREADCERT, N_("read a certificate from a data object")},
|
||||
{ "writecert", cmdWRITECERT, N_("store a certificate to a data object")},
|
||||
{ "writekey", cmdWRITEKEY, N_("store a private key to a data object")},
|
||||
{ "checkkeys", cmdCHECKKEYS, N_("run various checks on the keys")},
|
||||
{ "yubikey", cmdYUBIKEY, N_("Yubikey management commands")},
|
||||
{ "gpg", cmdGPG, NULL},
|
||||
{ "gpgsm", cmdGPGSM, NULL},
|
||||
@ -3903,6 +4037,7 @@ dispatch_command (card_info_t info, const char *orig_command)
|
||||
case cmdGPG: err = cmd_gpg (info, argstr, 0); break;
|
||||
case cmdGPGSM: err = cmd_gpg (info, argstr, 1); break;
|
||||
case cmdHISTORY: err = 0; break; /* Only used in interactive mode. */
|
||||
case cmdCHECKKEYS: err = cmd_checkkeys (info, argstr); break;
|
||||
|
||||
case cmdINVCMD:
|
||||
default:
|
||||
@ -4162,6 +4297,7 @@ interactive_loop (void)
|
||||
case cmdGPG: err = cmd_gpg (info, argstr, 0); break;
|
||||
case cmdGPGSM: err = cmd_gpg (info, argstr, 1); break;
|
||||
case cmdHISTORY: err = cmd_history (info, argstr); break;
|
||||
case cmdCHECKKEYS: err = cmd_checkkeys (info, argstr); break;
|
||||
|
||||
case cmdINVCMD:
|
||||
default:
|
||||
|
@ -246,6 +246,8 @@ gpg_error_t scd_cardlist (strlist_t *result);
|
||||
gpg_error_t scd_applist (strlist_t *result, int all);
|
||||
gpg_error_t scd_change_pin (const char *pinref, int reset_mode, int nullpin);
|
||||
gpg_error_t scd_checkpin (const char *serialno);
|
||||
gpg_error_t scd_havekey_info (const unsigned char *grip, char **r_result);
|
||||
gpg_error_t scd_delete_key (const unsigned char *grip, int force);
|
||||
|
||||
unsigned long agent_get_s2k_count (void);
|
||||
|
||||
|
118
tools/gpgconf.c
118
tools/gpgconf.c
@ -86,30 +86,31 @@ enum cmd_and_opt_values
|
||||
/* The list of commands and options. */
|
||||
static gpgrt_opt_t opts[] =
|
||||
{
|
||||
{ 300, NULL, 0, N_("@Commands:\n ") },
|
||||
ARGPARSE_group (300, N_("@Commands:\n ")),
|
||||
|
||||
{ aListComponents, "list-components", 256, N_("list all components") },
|
||||
{ aCheckPrograms, "check-programs", 256, N_("check all programs") },
|
||||
{ aListOptions, "list-options", 256, N_("|COMPONENT|list options") },
|
||||
{ aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") },
|
||||
{ aCheckOptions, "check-options", 256, N_("|COMPONENT|check options") },
|
||||
{ aApplyDefaults, "apply-defaults", 256,
|
||||
N_("apply global default values") },
|
||||
{ aApplyProfile, "apply-profile", 256,
|
||||
N_("|FILE|update configuration files using FILE") },
|
||||
{ aListDirs, "list-dirs", 256,
|
||||
N_("get the configuration directories for @GPGCONF@") },
|
||||
{ aListConfig, "list-config", 256,
|
||||
N_("list global configuration file") },
|
||||
{ aCheckConfig, "check-config", 256,
|
||||
N_("check global configuration file") },
|
||||
{ aQuerySWDB, "query-swdb", 256,
|
||||
N_("query the software version database") },
|
||||
{ aReload, "reload", 256, N_("reload all or a given component")},
|
||||
{ aLaunch, "launch", 256, N_("launch a given component")},
|
||||
{ aKill, "kill", 256, N_("kill a given component")},
|
||||
{ aCreateSocketDir, "create-socketdir", 256, "@"},
|
||||
{ aRemoveSocketDir, "remove-socketdir", 256, "@"},
|
||||
ARGPARSE_c (aListComponents, "list-components", N_("list all components")),
|
||||
ARGPARSE_c (aCheckPrograms, "check-programs", N_("check all programs")),
|
||||
ARGPARSE_c (aListOptions, "list-options", N_("|COMPONENT|list options")),
|
||||
ARGPARSE_c (aChangeOptions, "change-options",
|
||||
N_("|COMPONENT|change options")),
|
||||
ARGPARSE_c (aCheckOptions, "check-options", N_("|COMPONENT|check options")),
|
||||
ARGPARSE_c (aApplyDefaults, "apply-defaults",
|
||||
N_("apply global default values")),
|
||||
ARGPARSE_c (aApplyProfile, "apply-profile",
|
||||
N_("|FILE|update configuration files using FILE")),
|
||||
ARGPARSE_c (aListDirs, "list-dirs",
|
||||
N_("get the configuration directories for @GPGCONF@")),
|
||||
ARGPARSE_c (aListConfig, "list-config",
|
||||
N_("list global configuration file")),
|
||||
ARGPARSE_c (aCheckConfig, "check-config",
|
||||
N_("check global configuration file")),
|
||||
ARGPARSE_c (aQuerySWDB, "query-swdb",
|
||||
N_("query the software version database")),
|
||||
ARGPARSE_c (aReload, "reload", N_("reload all or a given component")),
|
||||
ARGPARSE_c (aLaunch, "launch", N_("launch a given component")),
|
||||
ARGPARSE_c (aKill, "kill", N_("kill a given component")),
|
||||
ARGPARSE_c (aCreateSocketDir, "create-socketdir", "@"),
|
||||
ARGPARSE_c (aRemoveSocketDir, "remove-socketdir", "@"),
|
||||
ARGPARSE_c (aShowVersions, "show-versions", ""),
|
||||
ARGPARSE_c (aShowConfigs, "show-configs", ""),
|
||||
/* hidden commands: for debugging */
|
||||
@ -117,24 +118,25 @@ static gpgrt_opt_t opts[] =
|
||||
ARGPARSE_c (aDotlockLock, "lock", "@"),
|
||||
ARGPARSE_c (aDotlockUnlock, "unlock", "@"),
|
||||
|
||||
{ 301, NULL, 0, N_("@\nOptions:\n ") },
|
||||
ARGPARSE_header (NULL, N_("@\nOptions:\n ")),
|
||||
|
||||
{ oOutput, "output", 2, N_("use as output file") },
|
||||
{ oVerbose, "verbose", 0, N_("verbose") },
|
||||
{ oQuiet, "quiet", 0, N_("quiet") },
|
||||
{ oDryRun, "dry-run", 0, N_("do not make any changes") },
|
||||
{ oRuntime, "runtime", 0, N_("activate changes at runtime, if possible") },
|
||||
ARGPARSE_s_s (oOutput, "output", N_("use as output file")),
|
||||
ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
|
||||
ARGPARSE_s_n (oQuiet, "quiet", N_("quiet")),
|
||||
ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
|
||||
ARGPARSE_s_n (oRuntime, "runtime",
|
||||
N_("activate changes at runtime, if possible")),
|
||||
ARGPARSE_s_i (oStatusFD, "status-fd",
|
||||
N_("|FD|write status info to this FD")),
|
||||
/* hidden options */
|
||||
{ oHomedir, "homedir", 2, "@" },
|
||||
{ oBuilddir, "build-prefix", 2, "@" },
|
||||
{ oNull, "null", 0, "@" },
|
||||
{ oNoVerbose, "no-verbose", 0, "@"},
|
||||
ARGPARSE_s_s (oHomedir, "homedir", "@"),
|
||||
ARGPARSE_s_s (oBuilddir, "build-prefix", "@"),
|
||||
ARGPARSE_s_n (oNull, "null", "@"),
|
||||
ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
|
||||
ARGPARSE_s_n (oShowSocket, "show-socket", "@"),
|
||||
ARGPARSE_s_s (oChUid, "chuid", "@"),
|
||||
|
||||
ARGPARSE_end(),
|
||||
ARGPARSE_end ()
|
||||
};
|
||||
|
||||
|
||||
@ -1072,12 +1074,12 @@ main (int argc, char **argv)
|
||||
#if !defined(HAVE_W32_SYSTEM)
|
||||
if (!fname)
|
||||
{
|
||||
es_fprintf (es_stderr, "usage: %s [options] lock|unlock NAME",
|
||||
GPGCONF_NAME);
|
||||
es_fprintf (es_stderr, "usage: %s --%slock NAME",
|
||||
GPGCONF_NAME, cmd==aDotlockUnlock?"un":"");
|
||||
es_putc ('\n', es_stderr);
|
||||
es_fputs (_("Need one NAME argument"), es_stderr);
|
||||
es_fputs ("Need name of file protected by the lock", es_stderr);
|
||||
es_putc ('\n', es_stderr);
|
||||
gpgconf_failure (GPG_ERR_USER_2);
|
||||
gpgconf_failure (GPG_ERR_SYNTAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1151,10 +1153,12 @@ get_revision_from_blurb (const char *blurb, int *r_len)
|
||||
static void
|
||||
show_version_gnupg (estream_t fp, const char *prefix)
|
||||
{
|
||||
char *fname, *p;
|
||||
char *fname, *p, *p0;
|
||||
size_t n;
|
||||
estream_t verfp;
|
||||
char line[100];
|
||||
char *line = NULL;
|
||||
size_t line_len = 0;
|
||||
ssize_t length;
|
||||
|
||||
es_fprintf (fp, "%s%sGnuPG %s (%s)\n%s%s\n", prefix, *prefix?"":"* ",
|
||||
gpgrt_strusage (13), BUILD_REVISION, prefix, gpgrt_strusage (17));
|
||||
@ -1173,20 +1177,46 @@ show_version_gnupg (estream_t fp, const char *prefix)
|
||||
verfp = es_fopen (fname, "r");
|
||||
if (!verfp)
|
||||
es_fprintf (fp, "%s[VERSION file not found]\n", prefix);
|
||||
else if (!es_fgets (line, sizeof line, verfp))
|
||||
es_fprintf (fp, "%s[VERSION file is empty]\n", prefix);
|
||||
else
|
||||
{
|
||||
int lnr = 0;
|
||||
|
||||
p0 = NULL;
|
||||
while ((length = es_read_line (verfp, &line, &line_len, NULL))>0)
|
||||
{
|
||||
lnr++;
|
||||
trim_spaces (line);
|
||||
for (p=line; *p; p++)
|
||||
if (lnr == 1 && *line != '[')
|
||||
{
|
||||
/* Old file format where we look only at the
|
||||
* first line. */
|
||||
p0 = line;
|
||||
break;
|
||||
}
|
||||
else if (!strncmp (line, "version=", 8))
|
||||
{
|
||||
p0 = line + 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (length < 0 || es_ferror (verfp))
|
||||
es_fprintf (fp, "%s[VERSION file read error]\n", prefix);
|
||||
else if (p0)
|
||||
{
|
||||
for (p=p0; *p; p++)
|
||||
if (*p < ' ' || *p > '~' || *p == '[')
|
||||
*p = '?';
|
||||
es_fprintf (fp, "%s%s\n", prefix, line);
|
||||
es_fprintf (fp, "%s%s\n", prefix, p0);
|
||||
}
|
||||
else
|
||||
es_fprintf (fp, "%s[VERSION file is empty]\n", prefix);
|
||||
|
||||
es_fclose (verfp);
|
||||
}
|
||||
}
|
||||
xfree (fname);
|
||||
}
|
||||
xfree (line);
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user