summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS46
-rw-r--r--agent/agent.h5
-rw-r--r--agent/call-pinentry.c268
-rw-r--r--agent/command.c170
-rw-r--r--agent/cvt-openpgp.c4
-rw-r--r--agent/divert-scd.c2
-rw-r--r--agent/genkey.c10
-rw-r--r--agent/gpg-agent.c4
-rw-r--r--agent/pkdecrypt.c4
-rw-r--r--agent/protect-tool.c5
-rw-r--r--common/audit.c1
-rw-r--r--common/compliance.c12
-rw-r--r--common/compliance.h8
-rw-r--r--common/logging.c15
-rw-r--r--common/logging.h11
-rw-r--r--common/openpgpdefs.h11
-rw-r--r--common/percent.c83
-rw-r--r--common/sexputil.c58
-rw-r--r--common/util.h20
-rw-r--r--configure.ac8
-rw-r--r--dirmngr/crlcache.c202
-rw-r--r--dirmngr/crlfetch.c123
-rw-r--r--dirmngr/dirmngr.c13
-rw-r--r--dirmngr/dns.c52
-rw-r--r--dirmngr/dns.h6
-rw-r--r--dirmngr/ldap-parse-uri.c2
-rw-r--r--dirmngr/misc.c2
-rw-r--r--dirmngr/ocsp.c2
-rw-r--r--dirmngr/validate.c195
-rw-r--r--doc/DETAILS35
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/gpgsm.texi19
-rw-r--r--g10/call-agent.c31
-rw-r--r--g10/call-agent.h3
-rw-r--r--g10/card-util.c49
-rw-r--r--g10/decrypt-data.c862
-rw-r--r--g10/dek.h24
-rw-r--r--g10/ecdh.c18
-rw-r--r--g10/encrypt.c37
-rw-r--r--g10/export.c8
-rw-r--r--g10/getkey.c23
-rw-r--r--g10/gpg.c6
-rw-r--r--g10/keyedit.c28
-rw-r--r--g10/keyid.c2
-rw-r--r--g10/keylist.c2
-rw-r--r--g10/main.h8
-rw-r--r--g10/mainproc.c196
-rw-r--r--g10/misc.c78
-rw-r--r--g10/packet.h32
-rw-r--r--g10/parse-packet.c140
-rw-r--r--g10/passphrase.c22
-rw-r--r--g10/pubkey-enc.c13
-rw-r--r--g10/sig-check.c2
-rw-r--r--g10/sign.c3
-rw-r--r--g13/call-syshelp.c2
-rw-r--r--g13/g13tuple.c6
-rw-r--r--po/POTFILES.in1
-rw-r--r--po/ca.po87
-rw-r--r--po/cs.po85
-rw-r--r--po/da.po91
-rw-r--r--po/de.po86
-rw-r--r--po/el.po87
-rw-r--r--po/eo.po87
-rw-r--r--po/es.po83
-rw-r--r--po/et.po87
-rw-r--r--po/fi.po87
-rw-r--r--po/fr.po87
-rw-r--r--po/gl.po87
-rw-r--r--po/hu.po104
-rw-r--r--po/id.po87
-rw-r--r--po/it.po87
-rw-r--r--po/ja.po82
-rw-r--r--po/nb.po83
-rw-r--r--po/pl.po85
-rw-r--r--po/pt.po85
-rw-r--r--po/ro.po87
-rw-r--r--po/ru.po83
-rw-r--r--po/sk.po87
-rw-r--r--po/sv.po87
-rw-r--r--po/tr.po89
-rw-r--r--po/uk.po87
-rw-r--r--po/zh_CN.po86
-rw-r--r--po/zh_TW.po83
-rw-r--r--scd/apdu.c20
-rw-r--r--scd/app-common.h19
-rw-r--r--scd/app-dinsig.c2
-rw-r--r--scd/app-help.c63
-rw-r--r--scd/app-nks.c46
-rw-r--r--scd/app-openpgp.c64
-rw-r--r--scd/app-p15.c1671
-rw-r--r--scd/app-sc-hsm.c2
-rw-r--r--scd/iso7816.c79
-rw-r--r--scd/iso7816.h19
-rw-r--r--sm/call-agent.c2
-rw-r--r--sm/call-dirmngr.c52
-rw-r--r--sm/certchain.c176
-rw-r--r--sm/certcheck.c329
-rw-r--r--sm/certdump.c83
-rw-r--r--sm/certreqgen.c41
-rw-r--r--sm/decrypt.c8
-rw-r--r--sm/encrypt.c5
-rw-r--r--sm/fingerprint.c37
-rw-r--r--sm/gpgsm.c6
-rw-r--r--sm/gpgsm.h15
-rw-r--r--sm/import.c2
-rw-r--r--sm/keylist.c17
-rw-r--r--sm/misc.c90
-rw-r--r--sm/sign.c2
-rw-r--r--sm/verify.c127
-rw-r--r--tools/send-mail.c2
110 files changed, 5964 insertions, 2265 deletions
diff --git a/NEWS b/NEWS
index 7ab0bb6..50aeb64 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,49 @@
+Noteworthy changes in version 2.2.21 (2020-07-09)
+-------------------------------------------------
+
+ * gpg: Improve symmetric decryption speed by about 25%.
+ See commit 144b95cc9d.
+
+ * gpg: Support decryption of AEAD encrypted data packets.
+
+ * gpg: Add option --no-include-key-block. [#4856]
+
+ * gpg: Allow for extra padding in ECDH. [#4908]
+
+ * gpg: Only a single pinentry is shown for symmetric encryption if
+ the pinentry supports this. [#4971]
+
+ * gpg: Print a note if no keys are given to --delete-key. [#4959]
+
+ * gpg,gpgsm: The ridiculous passphrase quality bar is not anymore
+ shown. [#2103]
+
+ * gpgsm: Certificates without a CRL distribution point are now
+ considered valid without looking up a CRL. The new option
+ --enable-issuer-based-crl-check can be used to revert to the
+ former behaviour.
+
+ * gpgsm: Support rsaPSS signature verification. [#4538]
+
+ * gpgsm: Unless CRL checking is disabled lookup a missing issuer
+ certificate using the certificate's authorityInfoAccess. [#4898]
+
+ * gpgsm: Print the certificate's serial number also in decimal
+ notation.
+
+ * gpgsm: Fix possible NULL-deref in messages of --gen-key. [#4895]
+
+ * scd: Support the CardOS 5 based D-Trust Card 3.1.
+
+ * dirmngr: Allow http URLs with "LOOKUP --url".
+
+ * wkd: Take name of sendmail from configure. Fixes an OpenBSD
+ specific bug. [#4886]
+
+ Release-info: https://dev.gnupg.org/T4897
+ See-also: gnupg-announce/2020q3/000446.html
+
+
Noteworthy changes in version 2.2.20 (2020-03-20)
-------------------------------------------------
diff --git a/agent/agent.h b/agent/agent.h
index e10e02b..8b5ae60 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -447,7 +447,8 @@ gpg_error_t agent_askpin (ctrl_t ctrl,
int agent_get_passphrase (ctrl_t ctrl, char **retpass,
const char *desc, const char *prompt,
const char *errtext, int with_qualitybar,
- const char *keyinfo, cache_mode_t cache_mode);
+ const char *keyinfo, cache_mode_t cache_mode,
+ struct pin_entry_info_s *pininfo);
int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok,
const char *notokay, int with_cancel);
int agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn);
@@ -484,7 +485,7 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
membuf_t *outbuf, int *r_padding);
/*-- genkey.c --*/
-int check_passphrase_constraints (ctrl_t ctrl, const char *pw,
+int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int no_empty,
char **failed_constraint);
gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
char **r_passphrase);
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index b0b5bcb..2af94c9 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -85,6 +85,7 @@ struct entry_parm_s
int lines;
size_t size;
unsigned char *buffer;
+ int status;
};
@@ -836,7 +837,7 @@ inq_quality (void *opaque, const char *line)
else
{
percent = estimate_passphrase_quality (pin);
- if (check_passphrase_constraints (NULL, pin, NULL))
+ if (check_passphrase_constraints (NULL, pin, 0, NULL))
percent = -percent;
snprintf (numbuf, sizeof numbuf, "%d", percent);
rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
@@ -953,6 +954,36 @@ build_cmd_setdesc (char *line, size_t linelen, const char *desc)
}
+/* Ask pinentry to get a pin by "GETPIN" command, spawning a thread
+ * detecting the socket's EOF. */
+static gpg_error_t
+do_getpin (ctrl_t ctrl, struct entry_parm_s *parm)
+{
+ gpg_error_t rc;
+ int saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
+
+ (void)ctrl;
+
+ assuan_begin_confidential (entry_ctx);
+ rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, parm,
+ inq_quality, entry_ctx,
+ pinentry_status_cb, &parm->status);
+ assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
+ /* Most pinentries out in the wild return the old Assuan error code
+ for canceled which gets translated to an assuan Cancel error and
+ not to the code for a user cancel. Fix this here. */
+ if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
+ rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
+ /* Change error code in case the window close button was clicked
+ to cancel the operation. */
+ if ((parm->status & PINENTRY_STATUS_CLOSE_BUTTON)
+ && gpg_err_code (rc) == GPG_ERR_CANCELED)
+ rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
+
+ return rc;
+}
+
+
/* Call the Entry and ask for the PIN. We do check for a valid PIN
number here and repeat it as long as we have invalid formed
@@ -970,7 +1001,6 @@ agent_askpin (ctrl_t ctrl,
struct entry_parm_s parm;
const char *errtext = NULL;
int is_pin = 0;
- int saveflag;
if (opt.batch)
return 0; /* fixme: we should return BAD PIN */
@@ -1114,25 +1144,8 @@ agent_askpin (ctrl_t ctrl,
return unlock_pinentry (ctrl, rc);
}
- saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
- assuan_begin_confidential (entry_ctx);
- rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
- inq_quality, entry_ctx,
- pinentry_status_cb, &pininfo->status);
- assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
- /* Most pinentries out in the wild return the old Assuan error code
- for canceled which gets translated to an assuan Cancel error and
- not to the code for a user cancel. Fix this here. */
- if (rc && gpg_err_source (rc)
- && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
- rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
-
-
- /* Change error code in case the window close button was clicked
- to cancel the operation. */
- if ((pininfo->status & PINENTRY_STATUS_CLOSE_BUTTON)
- && gpg_err_code (rc) == GPG_ERR_CANCELED)
- rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
+ rc = do_getpin (ctrl, &parm);
+ pininfo->status = parm.status;
if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
errtext = is_pin? L_("PIN too long")
@@ -1183,9 +1196,11 @@ agent_askpin (ctrl_t ctrl,
}
if ((pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
- /* The password was read from the cache. Don't count this
- against the retry count. */
- pininfo->failed_tries --;
+ {
+ /* The password was read from the cache. Don't count this
+ against the retry count. */
+ pininfo->failed_tries --;
+ }
}
return unlock_pinentry (ctrl, gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
@@ -1195,19 +1210,22 @@ agent_askpin (ctrl_t ctrl,
/* Ask for the passphrase using the supplied arguments. The returned
- passphrase needs to be freed by the caller. */
+ passphrase needs to be freed by the caller. PININFO is optional
+ and can be used to have constraints checinkg while the pinentry
+ dialog is open (like what we do in agent_askpin). This is very
+ similar to agent_akpin and we should eventually merge the two
+ functions. */
int
agent_get_passphrase (ctrl_t ctrl,
char **retpass, const char *desc, const char *prompt,
const char *errtext, int with_qualitybar,
- const char *keyinfo, cache_mode_t cache_mode)
+ const char *keyinfo, cache_mode_t cache_mode,
+ struct pin_entry_info_s *pininfo)
{
-
int rc;
+ int is_pin;
char line[ASSUAN_LINELENGTH];
struct entry_parm_s parm;
- int saveflag;
- unsigned int pinentry_status;
*retpass = NULL;
if (opt.batch)
@@ -1215,17 +1233,42 @@ agent_get_passphrase (ctrl_t ctrl,
if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
{
+ unsigned char *passphrase;
+ size_t size;
+
if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
return gpg_error (GPG_ERR_CANCELED);
- if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
+ if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK && pininfo)
{
- size_t size;
+ *pininfo->pin = 0; /* Reset the PIN. */
+ rc = pinentry_loopback (ctrl, "PASSPHRASE",
+ &passphrase, &size,
+ pininfo->max_length - 1);
+ if (rc)
+ return rc;
+ memcpy (&pininfo->pin, passphrase, size);
+ wipememory (passphrase, size);
+ xfree (passphrase);
+ pininfo->pin[size] = 0;
+ if (pininfo->check_cb)
+ {
+ /* More checks by utilizing the optional callback. */
+ pininfo->cb_errtext = NULL;
+ rc = pininfo->check_cb (pininfo);
+ }
+ return rc;
+
+ }
+ else if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
+ {
+ /* Legacy variant w/o PININFO. */
return pinentry_loopback (ctrl, "PASSPHRASE",
(unsigned char **)retpass, &size,
MAX_PASSPHRASE_LEN);
}
+
return gpg_error (GPG_ERR_NO_PIN_ENTRY);
}
@@ -1233,9 +1276,14 @@ agent_get_passphrase (ctrl_t ctrl,
if (rc)
return rc;
- if (!prompt)
- prompt = desc && strstr (desc, "PIN")? L_("PIN:"): L_("Passphrase:");
-
+ /* Set IS_PIN and if needed a default prompt. */
+ if (prompt)
+ is_pin = !!strstr (prompt, "PIN");
+ else
+ {
+ is_pin = desc && strstr (desc, "PIN");
+ prompt = is_pin? L_("PIN:"): L_("Passphrase:");
+ }
/* If we have a KEYINFO string and are normal, user, or ssh cache
mode, we tell that the Pinentry so it may use it for own caching
@@ -1256,7 +1304,6 @@ agent_get_passphrase (ctrl_t ctrl,
if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
return unlock_pinentry (ctrl, rc);
-
if (desc)
build_cmd_setdesc (line, DIM(line), desc);
else
@@ -1270,7 +1317,8 @@ agent_get_passphrase (ctrl_t ctrl,
if (rc)
return unlock_pinentry (ctrl, rc);
- if (with_qualitybar && opt.min_passphrase_len)
+ if ((with_qualitybar || (pininfo && pininfo->with_qualitybar))
+ && opt.min_passphrase_len)
{
rc = setup_qualitybar (ctrl);
if (rc)
@@ -1280,40 +1328,132 @@ agent_get_passphrase (ctrl_t ctrl,
if (errtext)
{
snprintf (line, DIM(line), "SETERROR %s", errtext);
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+ rc = assuan_transact (entry_ctx, line,
+ NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (ctrl, rc);
}
- memset (&parm, 0, sizeof parm);
- parm.size = ASSUAN_LINELENGTH/2 - 5;
- parm.buffer = gcry_malloc_secure (parm.size+10);
- if (!parm.buffer)
- return unlock_pinentry (ctrl, out_of_core ());
+ if (!pininfo)
+ {
+ /* Legacy method without PININFO. */
+ memset (&parm, 0, sizeof parm);
+ parm.size = ASSUAN_LINELENGTH/2 - 5;
+ parm.buffer = gcry_malloc_secure (parm.size+10);
+ if (!parm.buffer)
+ return unlock_pinentry (ctrl, out_of_core ());
- saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
- assuan_begin_confidential (entry_ctx);
- pinentry_status = 0;
- rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
- inq_quality, entry_ctx,
- pinentry_status_cb, &pinentry_status);
- assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
- /* Most pinentries out in the wild return the old Assuan error code
- for canceled which gets translated to an assuan Cancel error and
- not to the code for a user cancel. Fix this here. */
- if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
- rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
- /* Change error code in case the window close button was clicked
- to cancel the operation. */
- if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
- && gpg_err_code (rc) == GPG_ERR_CANCELED)
- rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
+ rc = do_getpin (ctrl, &parm);
+ if (rc)
+ xfree (parm.buffer);
+ else
+ *retpass = parm.buffer;
+ return unlock_pinentry (ctrl, rc);
+ }
- if (rc)
- xfree (parm.buffer);
- else
- *retpass = parm.buffer;
- return unlock_pinentry (ctrl, rc);
+ /* We got PININFO. */
+
+ if (pininfo->with_repeat)
+ {
+ snprintf (line, DIM(line), "SETREPEATERROR %s",
+ L_("does not match - try again"));
+ rc = assuan_transact (entry_ctx, line,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (rc)
+ pininfo->with_repeat = 0; /* Pinentry does not support it. */
+ }
+ pininfo->repeat_okay = 0;
+ pininfo->status = 0;
+
+ for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
+ {
+ memset (&parm, 0, sizeof parm);
+ parm.size = pininfo->max_length;
+ parm.buffer = (unsigned char*)pininfo->pin;
+ *pininfo->pin = 0; /* Reset the PIN. */
+
+ if (errtext)
+ {
+ /* TRANSLATORS: The string is appended to an error message in
+ the pinentry. The %s is the actual error message, the
+ two %d give the current and maximum number of tries. */
+ snprintf (line, DIM(line), L_("SETERROR %s (try %d of %d)"),
+ errtext, pininfo->failed_tries+1, pininfo->max_tries);
+ rc = assuan_transact (entry_ctx, line,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (rc)
+ return unlock_pinentry (ctrl, rc);
+ errtext = NULL;
+ }
+
+ if (pininfo->with_repeat)
+ {
+ snprintf (line, DIM(line), "SETREPEAT %s", L_("Repeat:"));
+ rc = assuan_transact (entry_ctx, line,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (rc)
+ return unlock_pinentry (ctrl, rc);
+ }
+
+ rc = do_getpin (ctrl, &parm);
+ pininfo->status = parm.status;
+ if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
+ errtext = is_pin? L_("PIN too long")
+ : L_("Passphrase too long");
+ else if (rc)
+ return unlock_pinentry (ctrl, rc);
+
+ if (!errtext && pininfo->min_digits)
+ {
+ /* do some basic checks on the entered PIN. */
+ if (!all_digitsp (pininfo->pin))
+ errtext = L_("Invalid characters in PIN");
+ else if (pininfo->max_digits
+ && strlen (pininfo->pin) > pininfo->max_digits)
+ errtext = L_("PIN too long");
+ else if (strlen (pininfo->pin) < pininfo->min_digits)
+ errtext = L_("PIN too short");
+ }
+
+ if (!errtext && pininfo->check_cb)
+ {
+ /* More checks by utilizing the optional callback. */
+ pininfo->cb_errtext = NULL;
+ rc = pininfo->check_cb (pininfo);
+ /* When pinentry cache causes an error, return now. */
+ if (rc && (pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
+ return unlock_pinentry (ctrl, rc);
+
+ if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE)
+ {
+ if (pininfo->cb_errtext)
+ errtext = pininfo->cb_errtext;
+ else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
+ || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
+ errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
+ }
+ else if (rc)
+ return unlock_pinentry (ctrl, rc);
+ }
+
+ if (!errtext)
+ {
+ if (pininfo->with_repeat
+ && (pininfo->status & PINENTRY_STATUS_PIN_REPEATED))
+ pininfo->repeat_okay = 1;
+ return unlock_pinentry (ctrl, 0); /* okay, got a PIN or passphrase */
+ }
+
+ if ((pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
+ {
+ /* The password was read from the Pinentry's own cache.
+ Don't count this against the retry count. */
+ pininfo->failed_tries--;
+ }
+ }
+
+ return unlock_pinentry (ctrl, gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
+ : GPG_ERR_BAD_PASSPHRASE));
}
diff --git a/agent/command.c b/agent/command.c
index c24fc80..ebbb42c 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -1400,9 +1400,22 @@ send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
}
+/* Callback function to compare the first entered PIN with the one
+ currently being entered. */
+static gpg_error_t
+reenter_passphrase_cmp_cb (struct pin_entry_info_s *pi)
+{
+ const char *pin1 = pi->check_cb_arg;
+
+ if (!strcmp (pin1, pi->pin))
+ return 0; /* okay */
+ return gpg_error (GPG_ERR_BAD_PASSPHRASE);
+}
+
+
static const char hlp_get_passphrase[] =
"GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]]\n"
- " [--qualitybar] <cache_id>\n"
+ " [--qualitybar] [--newsymkey] <cache_id>\n"
" [<error_message> <prompt> <description>]\n"
"\n"
"This function is usually used to ask for a passphrase to be used\n"
@@ -1424,6 +1437,9 @@ static const char hlp_get_passphrase[] =
"cache the user will not be asked to enter a passphrase but the error\n"
"code GPG_ERR_NO_DATA is returned. \n"
"\n"
+ "If the option\"--newsymkey\" is used the agent asks for a new passphrase\n"
+ "to be used in symmetric-only encryption. This must not be empty.\n"
+ "\n"
"If the option \"--qualitybar\" is used a visual indication of the\n"
"entered passphrase quality is shown. (Unless no minimum passphrase\n"
"length has been configured.)";
@@ -1433,13 +1449,19 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
ctrl_t ctrl = assuan_get_pointer (ctx);
int rc;
char *pw;
- char *response;
- char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
+ char *response = NULL;
+ char *response2 = NULL;
+ char *cacheid = NULL; /* May point into LINE. */
+ char *desc = NULL; /* Ditto */
+ char *prompt = NULL; /* Ditto */
+ char *errtext = NULL; /* Ditto */
const char *desc2 = _("Please re-enter this passphrase");
char *p;
- int opt_data, opt_check, opt_no_ask, opt_qualbar;
+ int opt_data, opt_check, opt_no_ask, opt_qualbar, opt_newsymkey;
int opt_repeat = 0;
char *entry_errtext = NULL;
+ struct pin_entry_info_s *pi = NULL;
+ struct pin_entry_info_s *pi2 = NULL;
if (ctrl->restricted)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
@@ -1456,6 +1478,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
opt_repeat = 1;
}
opt_qualbar = has_option (line, "--qualitybar");
+ opt_newsymkey = has_option (line, "--newsymkey");
line = skip_options (line);
cacheid = line;
@@ -1505,26 +1528,116 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
{
rc = send_back_passphrase (ctx, opt_data, pw);
xfree (pw);
+ goto leave;
}
else if (opt_no_ask)
- rc = gpg_error (GPG_ERR_NO_DATA);
- else
{
- /* Note, that we only need to replace the + characters and
- should leave the other escaping in place because the escaped
- string is send verbatim to the pinentry which does the
- unescaping (but not the + replacing) */
- if (errtext)
- plus_to_blank (errtext);
- if (prompt)
- plus_to_blank (prompt);
- if (desc)
- plus_to_blank (desc);
+ rc = gpg_error (GPG_ERR_NO_DATA);
+ goto leave;
+ }
+
+ /* Note, that we only need to replace the + characters and should
+ * leave the other escaping in place because the escaped string is
+ * send verbatim to the pinentry which does the unescaping (but not
+ * the + replacing) */
+ if (errtext)
+ plus_to_blank (errtext);
+ if (prompt)
+ plus_to_blank (prompt);
+ if (desc)
+ plus_to_blank (desc);
+ if (opt_newsymkey)
+ {
+ /* We do not want to break any existing usage of this command
+ * and thus we introduced the option --newsymkey to make this
+ * command more useful to query the passphrase for symmetric
+ * encryption. */
+ pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
+ if (!pi)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+ pi2 = gcry_calloc_secure (1, sizeof (*pi2) + MAX_PASSPHRASE_LEN + 1);
+ if (!pi2)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+ pi->max_length = MAX_PASSPHRASE_LEN + 1;
+ pi->max_tries = 3;
+ pi->with_qualitybar = opt_qualbar;
+ pi->with_repeat = opt_repeat;
+ pi2->max_length = MAX_PASSPHRASE_LEN + 1;
+ pi2->max_tries = 3;
+ pi2->check_cb = reenter_passphrase_cmp_cb;
+ pi2->check_cb_arg = pi->pin;
+
+ for (;;) /* (degenerated for-loop) */
+ {
+ xfree (response);
+ response = NULL;
+ rc = agent_get_passphrase (ctrl, &response,
+ desc,
+ prompt,
+ entry_errtext? entry_errtext:errtext,
+ opt_qualbar, cacheid, CACHE_MODE_USER,
+ pi);
+ if (rc)
+ goto leave;
+ xfree (entry_errtext);
+ entry_errtext = NULL;
+ /* We don't allow an empty passpharse in this mode. */
+ if (check_passphrase_constraints (ctrl, pi->pin, 1, &entry_errtext))
+ {
+ pi->failed_tries = 0;
+ pi2->failed_tries = 0;
+ continue;
+ }
+ if (*pi->pin && !pi->repeat_okay)
+ {
+ /* The passphrase is empty and the pinentry did not
+ * already run the repetition check, do it here. This
+ * is only called when using an old and simple pinentry. */
+ xfree (response);
+ response = NULL;
+ rc = agent_get_passphrase (ctrl, &response,
+ L_("Please re-enter this passphrase"),
+ prompt,
+ entry_errtext? entry_errtext:errtext,
+ opt_qualbar, cacheid, CACHE_MODE_USER,
+ pi2);
+ if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE)
+ { /* The re-entered passphrase one did not match and
+ * the user did not hit cancel. */
+ entry_errtext = xtrystrdup (L_("does not match - try again"));
+ if (!entry_errtext)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+ continue;
+ }
+ }
+ break;
+ }
+ if (!rc && *pi->pin)
+ {
+ /* Return the passphrase. */
+ if (cacheid)
+ agent_put_cache (ctrl, cacheid, CACHE_MODE_USER, pi->pin, 0);
+ rc = send_back_passphrase (ctx, opt_data, pi->pin);
+ }
+ }
+ else
+ {
next_try:
+ xfree (response);
+ response = NULL;
rc = agent_get_passphrase (ctrl, &response, desc, prompt,
entry_errtext? entry_errtext:errtext,
- opt_qualbar, cacheid, CACHE_MODE_USER);
+ opt_qualbar, cacheid, CACHE_MODE_USER, NULL);
xfree (entry_errtext);
entry_errtext = NULL;
if (!rc)
@@ -1532,27 +1645,24 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
int i;
if (opt_check
- && check_passphrase_constraints (ctrl, response, &entry_errtext))
+ && check_passphrase_constraints (ctrl, response,0,&entry_errtext))
{
- xfree (response);
goto next_try;
}
for (i = 0; i < opt_repeat; i++)
{
- char *response2;
-
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
break;
+ xfree (response2);
+ response2 = NULL;
rc = agent_get_passphrase (ctrl, &response2, desc2, prompt,
errtext, 0,
- cacheid, CACHE_MODE_USER);
+ cacheid, CACHE_MODE_USER, NULL);
if (rc)
break;
if (strcmp (response2, response))
{
- xfree (response2);
- xfree (response);
entry_errtext = try_percent_escape
(_("does not match - try again"), NULL);
if (!entry_errtext)
@@ -1562,7 +1672,6 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
}
goto next_try;
}
- xfree (response2);
}
if (!rc)
{
@@ -1570,10 +1679,15 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
agent_put_cache (ctrl, cacheid, CACHE_MODE_USER, response, 0);
rc = send_back_passphrase (ctx, opt_data, response);
}
- xfree (response);
}
}
+ leave:
+ xfree (response);
+ xfree (response2);
+ xfree (entry_errtext);
+ xfree (pi2);
+ xfree (pi);
return leave_cmd (ctx, rc);
}
@@ -3233,7 +3347,9 @@ command_has_option (const char *cmd, const char *cmdopt)
if (!strcmp (cmd, "GET_PASSPHRASE"))
{
if (!strcmp (cmdopt, "repeat"))
- return 1;
+ return 1;
+ if (!strcmp (cmdopt, "newsymkey"))
+ return 1;
}
return 0;
diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index bf05174..06cd1c8 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -878,11 +878,11 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, int dontcare_exist,
log_debug ("XXX pubkey_algo=%d\n", pubkey_algo);
log_debug ("XXX is_protected=%d\n", is_protected);
log_debug ("XXX protect_algo=%d\n", protect_algo);
- log_printhex ("XXX iv", iv, ivlen);
+ log_printhex (iv, ivlen, "XXX iv");
log_debug ("XXX ivlen=%d\n", ivlen);
log_debug ("XXX s2k_mode=%d\n", s2k_mode);
log_debug ("XXX s2k_algo=%d\n", s2k_algo);
- log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt);
+ log_printhex (s2k_salt, sizeof s2k_salt, "XXX s2k_salt");
log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count);
log_debug ("XXX curve='%s'\n", curve);
for (idx=0; skey[idx]; idx++)
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index 191ed7f..b79f7a8 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -169,7 +169,7 @@ encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
memcpy (frame, asn, asnlen);
memcpy (frame+asnlen, digest, digestlen);
if (DBG_CRYPTO)
- log_printhex ("encoded hash:", frame, asnlen+digestlen);
+ log_printhex (frame, asnlen+digestlen, "encoded hash:");
*r_val = frame;
*r_len = asnlen+digestlen;
diff --git a/agent/genkey.c b/agent/genkey.c
index d5c80d0..cddd67d 100644
--- a/agent/genkey.c
+++ b/agent/genkey.c
@@ -179,7 +179,7 @@ take_this_one_anyway (ctrl_t ctrl, const char *desc)
message describing the problem is returned in
*FAILED_CONSTRAINT. */
int
-check_passphrase_constraints (ctrl_t ctrl, const char *pw,
+check_passphrase_constraints (ctrl_t ctrl, const char *pw, int no_empty,
char **failed_constraint)
{
gpg_error_t err = 0;
@@ -198,7 +198,7 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw,
/* The first check is to warn about an empty passphrase. */
if (!*pw)
{
- const char *desc = (opt.enforce_passphrase_constraints?
+ const char *desc = (opt.enforce_passphrase_constraints || no_empty?
L_("You have not entered a passphrase!%0A"
"An empty passphrase is not allowed.") :
L_("You have not entered a passphrase - "
@@ -209,7 +209,7 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw,
err = 1;
if (failed_constraint)
{
- if (opt.enforce_passphrase_constraints)
+ if (opt.enforce_passphrase_constraints || no_empty)
*failed_constraint = xstrdup (desc);
else
err = take_this_one_anyway2 (ctrl, desc,
@@ -386,7 +386,7 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
}
pi->max_length = MAX_PASSPHRASE_LEN + 1;
pi->max_tries = 3;
- pi->with_qualitybar = 1;
+ pi->with_qualitybar = 0;
pi->with_repeat = 1;
pi2->max_length = MAX_PASSPHRASE_LEN + 1;
pi2->max_tries = 3;
@@ -399,7 +399,7 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
initial_errtext = NULL;
if (!err)
{
- if (check_passphrase_constraints (ctrl, pi->pin, &initial_errtext))
+ if (check_passphrase_constraints (ctrl, pi->pin, 0, &initial_errtext))
{
pi->failed_tries = 0;
pi2->failed_tries = 0;
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 27cb70c..3dcbbf8 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -2618,7 +2618,7 @@ putty_message_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
if (!data)
goto leave;
- /* log_printhex ("request:", data, 20); */
+ /* log_printhex (data, 20, "request:"); */
ctrl = xtrycalloc (1, sizeof *ctrl);
if (!ctrl)
@@ -2639,7 +2639,7 @@ putty_message_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
if (!serve_mmapped_ssh_request (ctrl, data, PUTTY_IPC_MAXLEN))
ret = 1; /* Valid ssh message has been constructed. */
agent_deinit_default_ctrl (ctrl);
- /* log_printhex (" reply:", data, 20); */
+ /* log_printhex (data, 20, " reply:"); */
leave:
xfree (ctrl);
diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c
index 46697ba..06a8e0b 100644
--- a/agent/pkdecrypt.c
+++ b/agent/pkdecrypt.c
@@ -64,8 +64,8 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
if (DBG_CRYPTO)
{
- log_printhex ("keygrip:", ctrl->keygrip, 20);
- log_printhex ("cipher: ", ciphertext, ciphertextlen);
+ log_printhex (ctrl->keygrip, 20, "keygrip:");
+ log_printhex (ciphertext, ciphertextlen, "cipher: ");
}
rc = agent_key_from_file (ctrl, NULL, desc_text,
ctrl->keygrip, &shadow_info,
diff --git a/agent/protect-tool.c b/agent/protect-tool.c
index 3bba5c6..00c0748 100644
--- a/agent/protect-tool.c
+++ b/agent/protect-tool.c
@@ -316,6 +316,11 @@ read_key (const char *fname)
buf = read_file (fname, &buflen);
if (!buf)
return NULL;
+ if (buflen >= 4 && !memcmp (buf, "Key:", 4))
+ {
+ log_error ("Extended key format is not supported by this tool\n");
+ return NULL;
+ }
key = make_canonical (fname, buf, buflen);
xfree (buf);
return key;
diff --git a/common/audit.c b/common/audit.c
index 179bf72..718f729 100644
--- a/common/audit.c
+++ b/common/audit.c
@@ -1105,6 +1105,7 @@ proc_type_verify (audit_ctx_t ctx)
switch (gpg_err_code (item->err))
{
case 0: ok = "good"; break;
+ case GPG_ERR_TRUE: ok = "n/a"; break;
case GPG_ERR_CERT_REVOKED: ok = "bad"; break;
case GPG_ERR_NOT_ENABLED: ok = "disabled"; break;
case GPG_ERR_NO_CRL_KNOWN:
diff --git a/common/compliance.c b/common/compliance.c
index 49aada1..7dbbbd3 100644
--- a/common/compliance.c
+++ b/common/compliance.c
@@ -96,6 +96,7 @@ gnupg_initialize_compliance (int gnupg_module_name)
* both are compatible from the point of view of this function. */
int
gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
+ unsigned int algo_flags,
gcry_mpi_t key[], unsigned int keylength,
const char *curvename)
{
@@ -148,6 +149,10 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
result = (keylength == 2048
|| keylength == 3072
|| keylength == 4096);
+ /* rsaPSS was not part of the evaluation and thus we don't
+ * claim compliance. */
+ if ((algo_flags & PK_ALGO_FLAG_RSAPSS))
+ result = 0;
break;
case is_dsa:
@@ -197,7 +202,8 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
* they produce, and liberal in what they accept. */
int
gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
- enum pk_use_case use, int algo, gcry_mpi_t key[],
+ enum pk_use_case use, int algo,
+ unsigned int algo_flags, gcry_mpi_t key[],
unsigned int keylength, const char *curvename)
{
int result = 0;
@@ -228,6 +234,10 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
default:
log_assert (!"reached");
}
+ /* rsaPSS was not part of the evaluation and thus we don't
+ * claim compliance. */
+ if ((algo_flags & PK_ALGO_FLAG_RSAPSS))
+ result = 0;
break;
case PUBKEY_ALGO_DSA:
diff --git a/common/compliance.h b/common/compliance.h
index 2076e79..21bd230 100644
--- a/common/compliance.h
+++ b/common/compliance.h
@@ -48,11 +48,17 @@ enum pk_use_case
PK_USE_SIGNING, PK_USE_VERIFICATION,
};
+/* Flags to distinguish public key algorithm variants. */
+#define PK_ALGO_FLAG_RSAPSS 1 /* Use rsaPSS padding. */
+
+
int gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
+ unsigned int algo_flags,
gcry_mpi_t key[], unsigned int keylength,
const char *curvename);
int gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
- enum pk_use_case use, int algo, gcry_mpi_t key[],
+ enum pk_use_case use, int algo,
+ unsigned int algo_flags, gcry_mpi_t key[],
unsigned int keylength, const char *curvename);
int gnupg_cipher_is_compliant (enum gnupg_compliance_mode compliance,
cipher_algo_t cipher,
diff --git a/common/logging.c b/common/logging.c
index df55e68..7fe8b74 100644
--- a/common/logging.c
+++ b/common/logging.c
@@ -1011,10 +1011,17 @@ log_flush (void)
dump, with TEXT just an empty string, print a trailing linefeed,
otherwise print an entire debug line. */
void
-log_printhex (const char *text, const void *buffer, size_t length)
+log_printhex (const void *buffer, size_t length, const char *fmt, ...)
{
- if (text && *text)
- log_debug ("%s ", text);
+ if (fmt && *fmt)
+ {
+ va_list arg_ptr ;
+
+ va_start (arg_ptr, fmt);
+ do_logv (GPGRT_LOG_DEBUG, 0, NULL, NULL, fmt, arg_ptr);
+ va_end (arg_ptr);
+ log_printf (" ");
+ }
if (length)
{
const unsigned char *p = buffer;
@@ -1022,7 +1029,7 @@ log_printhex (const char *text, const void *buffer, size_t length)
for (length--, p++; length--; p++)
log_printf (" %02X", *p);
}
- if (text)
+ if (fmt)
log_printf ("\n");
}
diff --git a/common/logging.h b/common/logging.h
index 2225100..cb1ec11 100644
--- a/common/logging.h
+++ b/common/logging.h
@@ -103,11 +103,12 @@ void log_debug_with_string (const char *string, const char *fmt,
void log_printf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2);
void log_flush (void);
-/* Print a hexdump of BUFFER. With TEXT passes as NULL print just the
- raw dump, with TEXT being an empty string, print a trailing
- linefeed, otherwise print an entire debug line with TEXT followed
- by the hexdump and a final LF. */
-void log_printhex (const char *text, const void *buffer, size_t length);
+/* Print a hexdump of BUFFER. With FMT passed as NULL print just the
+ * raw dump, with FMT being an empty string, print a trailing
+ * linefeed, otherwise print an entire debug line with expanded FMT
+ * followed by the hexdump and a final LF. */
+void log_printhex (const void *buffer, size_t length,
+ const char *fmt, ...) GPGRT_ATTR_PRINTF(3,4);
void log_clock (const char *string);
diff --git a/common/openpgpdefs.h b/common/openpgpdefs.h
index 4dcfc25..5cc437a 100644
--- a/common/openpgpdefs.h
+++ b/common/openpgpdefs.h
@@ -51,6 +51,7 @@ typedef enum
PKT_ATTRIBUTE = 17, /* PGP's attribute packet. */
PKT_ENCRYPTED_MDC = 18, /* Integrity protected encrypted data. */
PKT_MDC = 19, /* Manipulation detection code packet. */
+ PKT_ENCRYPTED_AEAD= 20, /* AEAD encrypted data packet. */
PKT_COMMENT = 61, /* new comment packet (GnuPG specific). */
PKT_GPG_CONTROL = 63 /* internal control packet (GnuPG specific). */
}
@@ -125,6 +126,16 @@ typedef enum
sigsubpkttype_t;
+/* Note that we encode the AEAD algo in a 3 bit field at some places. */
+typedef enum
+ {
+ AEAD_ALGO_NONE = 0,
+ AEAD_ALGO_EAX = 1,
+ AEAD_ALGO_OCB = 2
+ }
+aead_algo_t;
+
+
typedef enum
{
CIPHER_ALGO_NONE = 0,
diff --git a/common/percent.c b/common/percent.c
index 569c5fd..224de78 100644
--- a/common/percent.c
+++ b/common/percent.c
@@ -87,6 +87,89 @@ percent_plus_escape (const char *string)
}
+/* Create a newly malloced string from (DATA,DATALEN) with embedded
+ * nuls quoted as %00. The standard percent unescaping can be used to
+ * reverse this encoding. With PLUS_ESCAPE set plus-escaping (spaces
+ * are replaced by a '+') and escaping of characters with values less
+ * than 0x20 is used. If PREFIX is not NULL it will be prepended to
+ * the output in standard escape format; that is PLUS_ESCAPING is
+ * ignored for PREFIX. */
+char *
+percent_data_escape (int plus_escape, const char *prefix,
+ const void *data, size_t datalen)
+{
+ char *buffer, *p;
+ const unsigned char *s;
+ size_t n;
+ size_t length = 1;
+
+ if (prefix)
+ {
+ for (s = prefix; *s; s++)
+ {
+ if (*s == '%' || *s < 0x20)
+ length += 3;
+ else
+ length++;
+ }
+ }
+
+ for (s=data, n=datalen; n; s++, n--)
+ {
+ if (!*s || *s == '%' || (plus_escape && (*s < ' ' || *s == '+')))
+ length += 3;
+ else
+ length++;
+ }
+
+ buffer = p = xtrymalloc (length);
+ if (!buffer)
+ return NULL;
+
+ if (prefix)
+ {
+ for (s = prefix; *s; s++)
+ {
+ if (*s == '%' || *s < 0x20)
+ {
+ snprintf (p, 4, "%%%02X", *s);
+ p += 3;
+ }
+ else
+ *p++ = *s;
+ }
+ }
+
+ for (s=data, n=datalen; n; s++, n--)
+ {
+ if (!*s)
+ {
+ memcpy (p, "%00", 3);
+ p += 3;
+ }
+ else if (*s == '%')
+ {
+ memcpy (p, "%25", 3);
+ p += 3;
+ }
+ else if (plus_escape && *s == ' ')
+ {
+ *p++ = '+';
+ }
+ else if (plus_escape && (*s < ' ' || *s == '+'))
+ {
+ snprintf (p, 4, "%%%02X", *s);
+ p += 3;
+ }
+ else
+ *p++ = *s;
+ }
+ *p = 0;
+
+ return buffer;
+}
+
+
/* Do the percent and plus/space unescaping from STRING to BUFFER and
return the length of the valid buffer. Plus unescaping is only
done if WITHPLUS is true. An escaped Nul character will be
diff --git a/common/sexputil.c b/common/sexputil.c
index e8c8a34..9a79c05 100644
--- a/common/sexputil.c
+++ b/common/sexputil.c
@@ -640,3 +640,61 @@ pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid)
xfree (algoname);
return result;
}
+
+
+/* Map a pubkey algo id from gcrypt to a string. This is the same as
+ * gcry_pk_algo_name but makes sure that the ECC algo identifiers are
+ * not all mapped to "ECC". */
+const char *
+pubkey_algo_to_string (int algo)
+{
+ if (algo == GCRY_PK_ECDSA)
+ return "ECDSA";
+ else if (algo == GCRY_PK_ECDH)
+ return "ECDH";
+ else if (algo == GCRY_PK_EDDSA)
+ return "EdDSA";
+ else
+ return gcry_pk_algo_name (algo);
+}
+
+
+/* Map a hash algo id from gcrypt to a string. This is the same as
+ * gcry_md_algo_name but the returned string is lower case, as
+ * expected by libksba and it avoids some overhead. */
+const char *
+hash_algo_to_string (int algo)
+{
+ static const struct
+ {
+ const char *name;
+ int algo;
+ } hashnames[] =
+ {
+ { "sha256", GCRY_MD_SHA256 },
+ { "sha512", GCRY_MD_SHA512 },
+ { "sha1", GCRY_MD_SHA1 },
+ { "sha384", GCRY_MD_SHA384 },
+ { "sha224", GCRY_MD_SHA224 },
+ { "sha3-224", GCRY_MD_SHA3_224 },
+ { "sha3-256", GCRY_MD_SHA3_256 },
+ { "sha3-384", GCRY_MD_SHA3_384 },
+ { "sha3-512", GCRY_MD_SHA3_512 },
+ { "ripemd160", GCRY_MD_RMD160 },
+ { "rmd160", GCRY_MD_RMD160 },
+ { "md2", GCRY_MD_MD2 },
+ { "md4", GCRY_MD_MD4 },
+ { "tiger", GCRY_MD_TIGER },
+ { "haval", GCRY_MD_HAVAL },
+#if GCRYPT_VERSION_NUMBER >= 0x010900
+ { "sm3", GCRY_MD_SM3 },
+#endif
+ { "md5", GCRY_MD_MD5 }
+ };
+ int i;
+
+ for (i=0; i < DIM (hashnames); i++)
+ if (algo == hashnames[i].algo)
+ return hashnames[i].name;
+ return "?";
+}
diff --git a/common/util.h b/common/util.h
index 4d763f0..fd8a7dc 100644
--- a/common/util.h
+++ b/common/util.h
@@ -35,10 +35,19 @@
#include <errno.h> /* We need errno. */
#include <gpg-error.h> /* We need gpg_error_t and estream. */
-/* These error codes are used but not defined in the required
+/* These error codes might be used but not defined in the required
* libgpg-error version. Define them here.
* Example: (#if GPG_ERROR_VERSION_NUMBER < 0x011500 // 1.21)
*/
+#if GPG_ERROR_VERSION_NUMBER < 0x012400 /* 1.36 */
+# define GPG_ERR_NO_AUTH 314
+# define GPG_ERR_BAD_AUTH 315
+#endif
+
+#if GPG_ERROR_VERSION_NUMBER < 0x011b00 /* 1.27 */
+# define GPG_ERR_WRONG_NAME 313
+#endif
+
#if GPG_ERROR_VERSION_NUMBER < 0x011a00 /* 1.26 */
# define GPG_ERR_UNKNOWN_FLAG 309
# define GPG_ERR_INV_ORDER 310
@@ -66,6 +75,11 @@
/* Hash function used with libksba. */
#define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write)
+/* The length of the keygrip. This is a SHA-1 hash of the key
+ * parameters as generated by gcry_pk_get_keygrip. */
+#define KEYGRIP_LEN 20
+
+
/* Get all the stuff from jnlib. */
#include "../common/logging.h"
#include "../common/argparse.h"
@@ -207,6 +221,8 @@ int get_pk_algo_from_key (gcry_sexp_t key);
int get_pk_algo_from_canon_sexp (const unsigned char *keydata,
size_t keydatalen);
char *pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid);
+const char *pubkey_algo_to_string (int algo);
+const char *hash_algo_to_string (int algo);
/*-- convert.c --*/
int hex2bin (const char *string, void *buffer, size_t length);
@@ -219,6 +235,8 @@ char *hex2str_alloc (const char *hexstring, size_t *r_count);
/*-- percent.c --*/
char *percent_plus_escape (const char *string);
+char *percent_data_escape (int plus_escape, const char *prefix,
+ const void *data, size_t datalen);
char *percent_plus_unescape (const char *string, int nulrepl);
char *percent_unescape (const char *string, int nulrepl);
diff --git a/configure.ac b/configure.ac
index f3c9863..1d05d39 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ min_automake_version="1.14"
m4_define([mym4_package],[gnupg])
m4_define([mym4_major], [2])
m4_define([mym4_minor], [2])
-m4_define([mym4_micro], [20])
+m4_define([mym4_micro], [21])
# To start a new development series, i.e a new major or minor number
# you need to mark an arbitrary commit before the first beta release
@@ -54,7 +54,7 @@ AC_INIT([mym4_package],[mym4_version], [https://bugs.gnupg.org])
# build-aux/speedo.mk and Makefile.am
AC_DEFINE_UNQUOTED(GNUPG_SWDB_TAG, "gnupg22", [swdb tag for this branch])
-NEED_GPG_ERROR_VERSION=1.24
+NEED_GPG_ERROR_VERSION=1.25
NEED_LIBGCRYPT_API=1
NEED_LIBGCRYPT_VERSION=1.7.0
@@ -1220,6 +1220,8 @@ elif test x"$with_mailprog" != xno ; then
AC_SUBST(SENDMAIL,$with_mailprog)
AC_MSG_RESULT($with_mailprog)
fi
+AC_DEFINE_UNQUOTED(NAME_OF_SENDMAIL,"$SENDMAIL",
+ [Tool with sendmail -t interface])
#
@@ -1638,7 +1640,7 @@ if test "$GCC" = yes; then
AC_MSG_RESULT($_gcc_wopt)
fi
if test x"$_gcc_wopt" = xyes ; then
- mycflags="$mycflags -W -Wno-sign-compare"
+ mycflags="$mycflags -W -Wno-sign-compare -Wno-format-zero-length"
mycflags="$mycflags -Wno-missing-field-initializers"
fi
diff --git a/dirmngr/crlcache.c b/dirmngr/crlcache.c
index 52f49c0..cd35335 100644
--- a/dirmngr/crlcache.c
+++ b/dirmngr/crlcache.c
@@ -1351,7 +1351,7 @@ cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
{
log_error (_("WARNING: invalid cache record length for S/N "));
log_printf ("0x");
- log_printhex ("", sn, snlen);
+ log_printhex (sn, snlen, "");
}
else if (opt.verbose)
{
@@ -1531,17 +1531,104 @@ crl_cache_cert_isvalid (ctrl_t ctrl, ksba_cert_t cert,
}
+/* Return the hash algorithm's algo id from its name given in the
+ * non-null termnated string in (buffer,buflen). Returns 0 on failure
+ * or if the algo is not known. */
+static int
+hash_algo_from_buffer (const void *buffer, size_t buflen)
+{
+ char *string;
+ int algo;
+
+ string = xtrymalloc (buflen + 1);
+ if (!string)
+ {
+ log_error (_("out of core\n"));
+ return 0;
+ }
+ memcpy (string, buffer, buflen);
+ string[buflen] = 0;
+ algo = gcry_md_map_name (string);
+ if (!algo)
+ log_error ("unknown digest algorithm '%s' used in certificate\n", string);
+ xfree (string);
+ return algo;
+}
+
+
+/* Return an unsigned integer from the non-null termnated string
+ * (buffer,buflen). Returns 0 on failure. */
+static unsigned int
+uint_from_buffer (const void *buffer, size_t buflen)
+{
+ char *string;
+ unsigned int val;
+
+ string = xtrymalloc (buflen + 1);
+ if (!string)
+ {
+ log_error (_("out of core\n"));
+ return 0;
+ }
+ memcpy (string, buffer, buflen);
+ string[buflen] = 0;
+ val = strtoul (string, NULL, 10);
+ xfree (string);
+ return val;
+}
+
+
/* Prepare a hash context for the signature verification. Input is
the CRL and the output is the hash context MD as well as the uses
algorithm identifier ALGO. */
static gpg_error_t
-start_sig_check (ksba_crl_t crl, gcry_md_hd_t *md, int *algo)
+start_sig_check (ksba_crl_t crl, gcry_md_hd_t *md, int *algo, int *use_pss)
{
gpg_error_t err;
const char *algoid;
+ *use_pss = 0;
algoid = ksba_crl_get_digest_algo (crl);
- *algo = gcry_md_map_name (algoid);
+ if (algoid && !strcmp (algoid, "1.2.840.113549.1.1.10"))
+ {
+ /* Parse rsaPSS parameter. */
+ gcry_buffer_t ioarray[1] = { {0} };
+ ksba_sexp_t pssparam;
+ size_t n;
+ gcry_sexp_t psssexp;
+
+ pssparam = ksba_crl_get_sig_val (crl);
+ n = gcry_sexp_canon_len (pssparam, 0, NULL, NULL);
+ if (!n)
+ {
+ ksba_free (pssparam);
+ log_error (_("got an invalid S-expression from libksba\n"));
+ return gpg_error (GPG_ERR_INV_SEXP);
+ }
+ err = gcry_sexp_sscan (&psssexp, NULL, pssparam, n);
+ ksba_free (pssparam);
+ if (err)
+ {
+ log_error (_("converting S-expression failed: %s\n"),
+ gcry_strerror (err));
+ return err;
+ }
+
+ err = gcry_sexp_extract_param (psssexp, "sig-val",
+ "&'hash-algo'", ioarray, NULL);
+ gcry_sexp_release (psssexp);
+ if (err)
+ {
+ log_error ("extracting params from PSS failed: %s\n",
+ gpg_strerror (err));
+ return err;
+ }
+ *algo = hash_algo_from_buffer (ioarray[0].data, ioarray[0].len);
+ xfree (ioarray[0].data);
+ *use_pss = 1;
+ }
+ else
+ *algo = gcry_md_map_name (algoid);
if (!*algo)
{
log_error (_("unknown hash algorithm '%s'\n"), algoid? algoid:"?");
@@ -1570,15 +1657,13 @@ start_sig_check (ksba_crl_t crl, gcry_md_hd_t *md, int *algo)
certificate of the CRL issuer. This function takes ownership of MD. */
static gpg_error_t
finish_sig_check (ksba_crl_t crl, gcry_md_hd_t md, int algo,
- ksba_cert_t issuer_cert)
+ ksba_cert_t issuer_cert, int use_pss)
{
gpg_error_t err;
ksba_sexp_t sigval = NULL, pubkey = NULL;
- const char *s;
- char algoname[50];
size_t n;
gcry_sexp_t s_sig = NULL, s_hash = NULL, s_pkey = NULL;
- unsigned int i;
+ unsigned int saltlen = 0; /* (used only with use_pss) */
/* This also stops debugging on the MD. */
gcry_md_final (md);
@@ -1600,6 +1685,78 @@ finish_sig_check (ksba_crl_t crl, gcry_md_hd_t md, int algo,
goto leave;
}
+ if (use_pss)
+ {
+ /* Parse rsaPSS parameter which we should find in S_SIG. */
+ gcry_buffer_t ioarray[2] = { {0}, {0} };
+ ksba_sexp_t pssparam;
+ gcry_sexp_t psssexp;
+ int hashalgo;
+
+ pssparam = ksba_crl_get_sig_val (crl);
+ n = gcry_sexp_canon_len (pssparam, 0, NULL, NULL);
+ if (!n)
+ {
+ ksba_free (pssparam);
+ log_error (_("got an invalid S-expression from libksba\n"));
+ err = gpg_error (GPG_ERR_INV_SEXP);
+ goto leave;
+ }
+ err = gcry_sexp_sscan (&psssexp, NULL, pssparam, n);
+ ksba_free (pssparam);
+ if (err)
+ {
+ log_error (_("converting S-expression failed: %s\n"),
+ gcry_strerror (err));
+ goto leave;
+ }
+
+ err = gcry_sexp_extract_param (psssexp, "sig-val",
+ "&'hash-algo''salt-length'",
+ ioarray+0, ioarray+1, NULL);
+ gcry_sexp_release (psssexp);
+ if (err)
+ {
+ log_error ("extracting params from PSS failed: %s\n",
+ gpg_strerror (err));
+ goto leave;
+ }
+ hashalgo = hash_algo_from_buffer (ioarray[0].data, ioarray[0].len);
+ saltlen = uint_from_buffer (ioarray[1].data, ioarray[1].len);
+ xfree (ioarray[0].data);
+ xfree (ioarray[1].data);
+ if (hashalgo != algo)
+ {
+ log_error ("hash algo mismatch: %d announced but %d used\n",
+ algo, hashalgo);
+ return gpg_error (GPG_ERR_INV_CRL);
+ }
+ /* Add some restrictions; see ../sm/certcheck.c for details. */
+ switch (algo)
+ {
+ case GCRY_MD_SHA1:
+ case GCRY_MD_SHA256:
+ case GCRY_MD_SHA384:
+ case GCRY_MD_SHA512:
+ case GCRY_MD_SHA3_256:
+ case GCRY_MD_SHA3_384:
+ case GCRY_MD_SHA3_512:
+ break;
+ default:
+ log_error ("PSS hash algorithm '%s' rejected\n",
+ gcry_md_algo_name (algo));
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+
+ if (gcry_md_get_algo_dlen (algo) != saltlen)
+ {
+ log_error ("PSS hash algorithm '%s' rejected due to salt length %u\n",
+ gcry_md_algo_name (algo), saltlen);
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+ }
+
+
/* Get and convert the public key for the issuer certificate. */
if (DBG_X509)
dump_cert ("crl_issuer_cert", issuer_cert);
@@ -1620,13 +1777,25 @@ finish_sig_check (ksba_crl_t crl, gcry_md_hd_t md, int algo,
}
/* Create an S-expression with the actual hash value. */
- s = gcry_md_algo_name (algo);
- for (i = 0; *s && i < sizeof(algoname) - 1; s++, i++)
- algoname[i] = ascii_tolower (*s);
- algoname[i] = 0;
- err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))",
- algoname,
- gcry_md_get_algo_dlen (algo), gcry_md_read (md, algo));
+ if (use_pss)
+ {
+ err = gcry_sexp_build (&s_hash, NULL,
+ "(data (flags pss)"
+ "(hash %s %b)"
+ "(salt-length %u))",
+ hash_algo_to_string (algo),
+ (int)gcry_md_get_algo_dlen (algo),
+ gcry_md_read (md, algo),
+ saltlen);
+ }
+ else
+ {
+ err = gcry_sexp_build (&s_hash, NULL,
+ "(data(flags pkcs1)(hash %s %b))",
+ hash_algo_to_string (algo),
+ (int)gcry_md_get_algo_dlen (algo),
+ gcry_md_read (md, algo));
+ }
if (err)
{
log_error (_("creating S-expression failed: %s\n"), gcry_strerror (err));
@@ -1688,6 +1857,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
ksba_cert_t crlissuer_cert = NULL;
gcry_md_hd_t md = NULL;
int algo = 0;
+ int use_pss = 0;
size_t n;
(void)fname;
@@ -1710,7 +1880,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
{
case KSBA_SR_BEGIN_ITEMS:
{
- err = start_sig_check (crl, &md, &algo);
+ err = start_sig_check (crl, &md, &algo, &use_pss);
if (err)
goto failure;
@@ -1847,7 +2017,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
goto failure;
}
- err = finish_sig_check (crl, md, algo, crlissuer_cert);
+ err = finish_sig_check (crl, md, algo, crlissuer_cert, use_pss);
md = NULL; /* Closed. */
if (err)
{
diff --git a/dirmngr/crlfetch.c b/dirmngr/crlfetch.c
index 57ac51b..7da3d8b 100644
--- a/dirmngr/crlfetch.c
+++ b/dirmngr/crlfetch.c
@@ -408,40 +408,124 @@ end_cert_fetch (cert_fetch_context_t context)
}
+/* Read a certificate from an HTTP URL and return it as an estream
+ * memory buffer at R_FP. */
+static gpg_error_t
+read_cert_via_http (ctrl_t ctrl, const char *url, estream_t *r_fp)
+{
+ gpg_error_t err;
+ estream_t fp = NULL;
+ estream_t httpfp = NULL;
+ size_t nread, nwritten;
+ char buffer[1024];
+
+ if ((err = ks_http_fetch (ctrl, url, KS_HTTP_FETCH_TRUST_CFG, &httpfp)))
+ goto leave;
+
+ /* We now read the data from the web server into a memory buffer.
+ * To DOS we limit the certificate length to 32k. */
+ fp = es_fopenmem (32*1024, "rw");
+ if (!fp)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ for (;;)
+ {
+ if (es_read (httpfp, buffer, sizeof buffer, &nread))
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error reading '%s': %s\n",
+ es_fname_get (httpfp), gpg_strerror (err));
+ goto leave;
+ }
+
+ if (!nread)
+ break; /* Ready. */
+ if (es_write (fp, buffer, nread, &nwritten))
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error writing '%s': %s\n",
+ es_fname_get (fp), gpg_strerror (err));
+ goto leave;
+ }
+ else if (nread != nwritten)
+ {
+ err = gpg_error (GPG_ERR_EIO);
+ log_error ("error writing '%s': %s\n",
+ es_fname_get (fp), "short write");
+ goto leave;
+ }
+ }
+
+ es_rewind (fp);
+ *r_fp = fp;
+ fp = NULL;
+
+ leave:
+ es_fclose (httpfp);
+ es_fclose (fp);
+ return err;
+}
+
+
/* Lookup a cert by it's URL. */
gpg_error_t
fetch_cert_by_url (ctrl_t ctrl, const char *url,
unsigned char **value, size_t *valuelen)
{
- const unsigned char *cert_image;
+ const unsigned char *cert_image = NULL;
size_t cert_image_n;
- ksba_reader_t reader;
- ksba_cert_t cert;
+ ksba_reader_t reader = NULL;
+ ksba_cert_t cert = NULL;
gpg_error_t err;
*value = NULL;
*valuelen = 0;
- cert_image = NULL;
- reader = NULL;
- cert = NULL;
-
-#if USE_LDAP
- err = url_fetch_ldap (ctrl, url, NULL, 0, &reader);
-#else
- (void)ctrl;
- (void)url;
- err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-#endif /*USE_LDAP*/
- if (err)
- goto leave;
err = ksba_cert_new (&cert);
if (err)
goto leave;
- err = ksba_cert_read_der (cert, reader);
- if (err)
- goto leave;
+ if (url && (!strncmp (url, "http:", 5) || !strncmp (url, "https:", 6)))
+ {
+ estream_t stream;
+ void *der;
+ size_t derlen;
+
+ err = read_cert_via_http (ctrl, url, &stream);
+ if (err)
+ goto leave;
+
+ if (es_fclose_snatch (stream, &der, &derlen))
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ err = ksba_cert_init_from_mem (cert, der, derlen);
+ xfree (der);
+ if (err)
+ goto leave;
+ }
+ else /* Assume LDAP. */
+ {
+#if USE_LDAP
+ err = url_fetch_ldap (ctrl, url, NULL, 0, &reader);
+#else
+ (void)ctrl;
+ (void)url;
+ err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+#endif /*USE_LDAP*/
+ if (err)
+ goto leave;
+
+ err = ksba_cert_read_der (cert, reader);
+ if (err)
+ goto leave;
+ }
cert_image = ksba_cert_get_image (cert, &cert_image_n);
if (!cert_image || !cert_image_n)
@@ -461,7 +545,6 @@ fetch_cert_by_url (ctrl_t ctrl, const char *url,
*valuelen = cert_image_n;
leave:
-
ksba_cert_release (cert);
#if USE_LDAP
ldap_wrapper_release_context (reader);
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index 3ec6139..3beaab8 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -373,7 +373,7 @@ static npth_key_t my_tlskey_current_fd;
/* Prototypes. */
static void cleanup (void);
#if USE_LDAP
-static ldap_server_t parse_ldapserver_file (const char* filename);
+static ldap_server_t parse_ldapserver_file (const char* filename, int ienoent);
#endif /*USE_LDAP*/
static fingerprint_list_t parse_ocsp_signer (const char *string);
static void netactivity_action (void);
@@ -1100,11 +1100,11 @@ main (int argc, char **argv)
ldapfile = make_filename (gnupg_homedir (),
"dirmngr_ldapservers.conf",
NULL);
- opt.ldapservers = parse_ldapserver_file (ldapfile);
+ opt.ldapservers = parse_ldapserver_file (ldapfile, 1);
xfree (ldapfile);
}
else
- opt.ldapservers = parse_ldapserver_file (ldapfile);
+ opt.ldapservers = parse_ldapserver_file (ldapfile, 0);
#endif /*USE_LDAP*/
#ifndef HAVE_W32_SYSTEM
@@ -1618,7 +1618,7 @@ dirmngr_deinit_default_ctrl (ctrl_t ctrl)
*/
#if USE_LDAP
static ldap_server_t
-parse_ldapserver_file (const char* filename)
+parse_ldapserver_file (const char* filename, int ignore_enoent)
{
char buffer[1024];
char *p;
@@ -1631,7 +1631,10 @@ parse_ldapserver_file (const char* filename)
if (!fp)
{
if (errno == ENOENT)
- log_info ("No ldapserver file at: '%s'\n", filename);
+ {
+ if (!ignore_enoent)
+ log_info ("No ldapserver file at: '%s'\n", filename);
+ }
else
log_error (_("error opening '%s': %s\n"), filename,
strerror (errno));
diff --git a/dirmngr/dns.c b/dirmngr/dns.c
index 4c3b559..43845eb 100644
--- a/dirmngr/dns.c
+++ b/dirmngr/dns.c
@@ -2150,6 +2150,7 @@ static size_t dns_p_lines_fmt(void *dst, size_t lim, dns_error_t *_error, const
static size_t dns_p_lines(void *dst, size_t lim, dns_error_t *_error, struct dns_packet *P, struct dns_rr_i *I, struct dns_p_lines_i *state) {
int error, pc;
size_t len;
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
*_error = 0;
@@ -2168,7 +2169,7 @@ static size_t dns_p_lines(void *dst, size_t lim, dns_error_t *_error, struct dns
while (dns_rr_grep(&state->rr, 1, I, P, &error)) {
if (state->section != state->rr.section) {
DNS_P_LINE("\n");
- DNS_P_LINE(";; [%s:%d]\n", dns_strsection(state->rr.section), dns_p_count(P, state->rr.section));
+ DNS_P_LINE(";; [%s:%d]\n", dns_strsection(state->rr.section, __dst), dns_p_count(P, state->rr.section));
}
if (!(len = dns_rr_print(dst, lim, &state->rr, P, &error)))
@@ -3274,6 +3275,7 @@ size_t dns_rr_print(void *_dst, size_t lim, struct dns_rr *rr, struct dns_packet
union dns_any any;
size_t n;
int error;
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
if (rr->section == DNS_S_QD)
dns_b_putc(&dst, ';');
@@ -3288,9 +3290,9 @@ size_t dns_rr_print(void *_dst, size_t lim, struct dns_rr *rr, struct dns_packet
}
dns_b_putc(&dst, ' ');
- dns_b_puts(&dst, dns_strclass(rr->class));
+ dns_b_puts(&dst, dns_strclass(rr->class, __dst));
dns_b_putc(&dst, ' ');
- dns_b_puts(&dst, dns_strtype(rr->type));
+ dns_b_puts(&dst, dns_strtype(rr->type, __dst));
if (rr->section == DNS_S_QD)
goto epilog;
@@ -4864,6 +4866,7 @@ dns_error_t dns_trace_dump(struct dns_trace *trace, FILE *fp) {
dns_microseconds_t begin, elapsed;
} state = { 0 };
int error;
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
if (!trace || !trace->fp)
return EINVAL;
@@ -4886,8 +4889,8 @@ dns_error_t dns_trace_dump(struct dns_trace *trace, FILE *fp) {
fprintf(fp, "dns_res_submit:\n");
dns_trace_dump_meta(trace, " ", te, state.elapsed, fp);
fprintf(fp, " qname: %s\n", te->res_submit.qname);
- fprintf(fp, " qtype: %s\n", dns_strtype(te->res_submit.qtype));
- fprintf(fp, " qclass: %s\n", dns_strclass(te->res_submit.qclass));
+ fprintf(fp, " qtype: %s\n", dns_strtype(te->res_submit.qtype, __dst));
+ fprintf(fp, " qclass: %s\n", dns_strclass(te->res_submit.qclass, __dst));
dns_trace_dump_error(trace, " error: ", te->res_submit.error, fp);
break;
case DNS_TE_RES_FETCH:
@@ -10010,16 +10013,17 @@ int dns_ai_poll(struct dns_addrinfo *ai, int timeout) {
size_t dns_ai_print(void *_dst, size_t lim, struct addrinfo *ent, struct dns_addrinfo *ai) {
struct dns_buf dst = DNS_B_INTO(_dst, lim);
char addr[DNS_PP_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1];
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
dns_b_puts(&dst, "[ ");
dns_b_puts(&dst, ai->qname);
dns_b_puts(&dst, " IN ");
if (ai->qtype) {
- dns_b_puts(&dst, dns_strtype(ai->qtype));
+ dns_b_puts(&dst, dns_strtype(ai->qtype, __dst));
} else if (ent->ai_family == AF_INET) {
- dns_b_puts(&dst, dns_strtype(DNS_T_A));
+ dns_b_puts(&dst, dns_strtype(DNS_T_A, __dst));
} else if (ent->ai_family == AF_INET6) {
- dns_b_puts(&dst, dns_strtype(DNS_T_AAAA));
+ dns_b_puts(&dst, dns_strtype(DNS_T_AAAA, __dst));
} else {
dns_b_puts(&dst, "0");
}
@@ -10106,9 +10110,8 @@ static const struct {
{ "AR", DNS_S_ADDITIONAL },
};
-const char *(dns_strsection)(enum dns_section section) {
- char _dst[DNS_STRMAXLEN + 1] = { 0 };
- struct dns_buf dst = DNS_B_INTO(_dst, sizeof _dst);
+const char *(dns_strsection)(enum dns_section section, char *_dst) {
+ struct dns_buf dst = DNS_B_INTO(_dst, DNS_STRMAXLEN + 1);
unsigned i;
for (i = 0; i < lengthof(dns_sections); i++) {
@@ -10156,9 +10159,8 @@ static const struct {
{ "IN", DNS_C_IN },
};
-const char *(dns_strclass)(enum dns_class type) {
- char _dst[DNS_STRMAXLEN + 1] = { 0 };
- struct dns_buf dst = DNS_B_INTO(_dst, sizeof _dst);
+const char *(dns_strclass)(enum dns_class type, char *_dst) {
+ struct dns_buf dst = DNS_B_INTO(_dst, DNS_STRMAXLEN + 1);
unsigned i;
for (i = 0; i < lengthof(dns_classes); i++) {
@@ -10193,9 +10195,8 @@ enum dns_class dns_iclass(const char *name) {
} /* dns_iclass() */
-const char *(dns_strtype)(enum dns_type type) {
- char _dst[DNS_STRMAXLEN + 1] = { 0 };
- struct dns_buf dst = DNS_B_INTO(_dst, sizeof _dst);
+const char *(dns_strtype)(enum dns_type type, char *_dst) {
+ struct dns_buf dst = DNS_B_INTO(_dst, DNS_STRMAXLEN + 1);
unsigned i;
for (i = 0; i < lengthof(dns_rrtypes); i++) {
@@ -10618,6 +10619,7 @@ static int parse_packet(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
union dns_any any;
char pretty[sizeof any * 2];
size_t len;
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
P->end = fread(P->data, 1, P->size, stdin);
@@ -10634,7 +10636,7 @@ static int parse_packet(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
dns_rr_foreach(&rr, P, .sort = MAIN.sort) {
if (section != rr.section)
- fprintf(stdout, "\n;; [%s:%d]\n", dns_strsection(rr.section), dns_p_count(P, rr.section));
+ fprintf(stdout, "\n;; [%s:%d]\n", dns_strsection(rr.section, __dst), dns_p_count(P, rr.section));
if ((len = dns_rr_print(pretty, sizeof pretty, &rr, P, &error)))
fprintf(stdout, "%s\n", pretty);
@@ -10665,7 +10667,7 @@ static int parse_packet(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
rr = rrset[i];
#endif
if (section != rr.section)
- fprintf(stdout, "\n;; [%s:%d]\n", dns_strsection(rr.section), dns_p_count(Q, rr.section));
+ fprintf(stdout, "\n;; [%s:%d]\n", dns_strsection(rr.section, __dst), dns_p_count(Q, rr.section));
if ((len = dns_rr_print(pretty, sizeof pretty, &rr, Q, &error)))
fprintf(stdout, "%s\n", pretty);
@@ -10944,6 +10946,7 @@ static int send_query(int argc, char *argv[]) {
struct dns_socket *so;
int error, type;
struct dns_options opts = { 0 };
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
memset(&ss, 0, sizeof ss);
if (argc > 1) {
@@ -10976,7 +10979,7 @@ static int send_query(int argc, char *argv[]) {
else
type = dns_res_tcp2type(resconf()->options.tcp);
- fprintf(stderr, "querying %s for %s IN %s\n", host, MAIN.qname, dns_strtype(MAIN.qtype));
+ fprintf(stderr, "querying %s for %s IN %s\n", host, MAIN.qname, dns_strtype(MAIN.qtype, __dst));
if (!(so = dns_so_open((struct sockaddr *)&resconf()->iface, type, &opts, &error)))
panic("dns_so_open: %s", dns_strerror(error));
@@ -11227,11 +11230,12 @@ static int echo_port(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
static int isection(int argc, char *argv[]) {
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
const char *name = (argc > 1)? argv[1] : "";
int type;
type = dns_isection(name);
- name = dns_strsection(type);
+ name = dns_strsection(type, __dst);
printf("%s (%d)\n", name, type);
@@ -11240,11 +11244,12 @@ static int isection(int argc, char *argv[]) {
static int iclass(int argc, char *argv[]) {
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
const char *name = (argc > 1)? argv[1] : "";
int type;
type = dns_iclass(name);
- name = dns_strclass(type);
+ name = dns_strclass(type, __dst);
printf("%s (%d)\n", name, type);
@@ -11253,11 +11258,12 @@ static int iclass(int argc, char *argv[]) {
static int itype(int argc, char *argv[]) {
+ char __dst[DNS_STRMAXLEN + 1] = { 0 };
const char *name = (argc > 1)? argv[1] : "";
int type;
type = dns_itype(name);
- name = dns_strtype(type);
+ name = dns_strtype(type, __dst);
printf("%s (%d)\n", name, type);
diff --git a/dirmngr/dns.h b/dirmngr/dns.h
index 024d6dc..1f647e1 100644
--- a/dirmngr/dns.h
+++ b/dirmngr/dns.h
@@ -272,15 +272,15 @@ enum dns_rcode {
*/
#define DNS_STRMAXLEN 47 /* "QUESTION|ANSWER|AUTHORITY|ADDITIONAL" */
-DNS_PUBLIC const char *dns_strsection(enum dns_section);
+DNS_PUBLIC const char *dns_strsection(enum dns_section, char *);
DNS_PUBLIC enum dns_section dns_isection(const char *);
-DNS_PUBLIC const char *dns_strclass(enum dns_class);
+DNS_PUBLIC const char *dns_strclass(enum dns_class, char *);
DNS_PUBLIC enum dns_class dns_iclass(const char *);
-DNS_PUBLIC const char *dns_strtype(enum dns_type);
+DNS_PUBLIC const char *dns_strtype(enum dns_type, char *);
DNS_PUBLIC enum dns_type dns_itype(const char *);
diff --git a/dirmngr/ldap-parse-uri.c b/dirmngr/ldap-parse-uri.c
index 94d4efd..cae0351 100644
--- a/dirmngr/ldap-parse-uri.c
+++ b/dirmngr/ldap-parse-uri.c
@@ -54,7 +54,7 @@ ldap_uri_p (const char *url)
&& (url[3] == 'p' || url[3] == 'P')
&& (url[4] == ':'
|| ((url[4] == 's' || url[4] == 'S'
- || url[4] == 'i' || url[4] == 'i')
+ || url[4] == 'i' || url[4] == 'I')
&& url[5] == ':'))))
return 1;
return 0;
diff --git a/dirmngr/misc.c b/dirmngr/misc.c
index eef04ed..ba47c99 100644
--- a/dirmngr/misc.c
+++ b/dirmngr/misc.c
@@ -284,7 +284,7 @@ dump_string (const char *string)
else
{
log_printf ( "[ ");
- log_printhex (NULL, string, strlen (string));
+ log_printhex (string, strlen (string), NULL);
log_printf ( " ]");
}
}
diff --git a/dirmngr/ocsp.c b/dirmngr/ocsp.c
index 13e6120..eaa6ca2 100644
--- a/dirmngr/ocsp.c
+++ b/dirmngr/ocsp.c
@@ -305,7 +305,7 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp,
if (opt.verbose)
log_info (_("OCSP responder at '%s' status: %s\n"), url, t);
- /* Get the signature value now because we can all this fucntion
+ /* Get the signature value now because we can call this function
* only once. */
*r_sigval = ksba_ocsp_get_sig_val (ocsp, r_produced_at);
diff --git a/dirmngr/validate.c b/dirmngr/validate.c
index 371852b..901c165 100644
--- a/dirmngr/validate.c
+++ b/dirmngr/validate.c
@@ -888,6 +888,53 @@ pk_algo_from_sexp (gcry_sexp_t pkey)
}
+/* Return the hash algorithm's algo id from its name given in the
+ * non-null termnated string in (buffer,buflen). Returns 0 on failure
+ * or if the algo is not known. */
+static int
+hash_algo_from_buffer (const void *buffer, size_t buflen)
+{
+ char *string;
+ int algo;
+
+ string = xtrymalloc (buflen + 1);
+ if (!string)
+ {
+ log_error (_("out of core\n"));
+ return 0;
+ }
+ memcpy (string, buffer, buflen);
+ string[buflen] = 0;
+ algo = gcry_md_map_name (string);
+ if (!algo)
+ log_error ("unknown digest algorithm '%s' used in certificate\n", string);
+ xfree (string);
+ return algo;
+}
+
+
+/* Return an unsigned integer from the non-null termnated string
+ * (buffer,buflen). Returns 0 on failure. */
+static unsigned int
+uint_from_buffer (const void *buffer, size_t buflen)
+{
+ char *string;
+ unsigned int val;
+
+ string = xtrymalloc (buflen + 1);
+ if (!string)
+ {
+ log_error (_("out of core\n"));
+ return 0;
+ }
+ memcpy (string, buffer, buflen);
+ string[buflen] = 0;
+ val = strtoul (string, NULL, 10);
+ xfree (string);
+ return val;
+}
+
+
/* Check the signature on CERT using the ISSUER_CERT. This function
* does only test the cryptographic signature and nothing else. It is
* assumed that the ISSUER_CERT is valid. */
@@ -897,45 +944,26 @@ check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
gpg_error_t err;
const char *algoid;
gcry_md_hd_t md;
- int i, algo;
+ int algo;
ksba_sexp_t p;
size_t n;
gcry_sexp_t s_sig, s_hash, s_pkey;
- const char *s;
- char algo_name[16+1]; /* hash algorithm name converted to lower case. */
+ const char *algo_name; /* hash algorithm name converted to lower case. */
int digestlen;
unsigned char *digest;
+ int use_pss = 0;
+ unsigned int saltlen;
/* Hash the target certificate using the algorithm from that certificate. */
algoid = ksba_cert_get_digest_algo (cert);
algo = gcry_md_map_name (algoid);
- if (!algo)
+ if (!algo && algoid && !strcmp (algoid, "1.2.840.113549.1.1.10"))
+ use_pss = 1;
+ else if (!algo)
{
log_error (_("unknown hash algorithm '%s'\n"), algoid? algoid:"?");
return gpg_error (GPG_ERR_GENERAL);
}
- s = gcry_md_algo_name (algo);
- for (i=0; *s && i < sizeof algo_name - 1; s++, i++)
- algo_name[i] = tolower (*s);
- algo_name[i] = 0;
-
- err = gcry_md_open (&md, algo, 0);
- if (err)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (err));
- return err;
- }
- if (DBG_HASHING)
- gcry_md_debug (md, "hash.cert");
-
- err = ksba_cert_hash (cert, 1, HASH_FNC, md);
- if (err)
- {
- log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (err));
- gcry_md_close (md);
- return err;
- }
- gcry_md_final (md);
/* Get the signature value out of the target certificate. */
p = ksba_cert_get_sig_val (cert);
@@ -943,27 +971,96 @@ check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
- gcry_md_close (md);
ksba_free (p);
return gpg_error (GPG_ERR_BUG);
}
+ err = gcry_sexp_sscan ( &s_sig, NULL, p, n);
+ ksba_free (p);
+ if (err)
+ {
+ log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (err));
+ return err;
+ }
if (DBG_CRYPTO)
+ gcry_log_debugsxp ("sigval", s_sig);
+
+ if (use_pss)
{
- int j;
- log_debug ("signature value:");
- for (j=0; j < n; j++)
- log_printf (" %02X", p[j]);
- log_printf ("\n");
+ /* Extract the hash algorithm and the salt length from the sigval. */
+ gcry_buffer_t ioarray[2] = { {0}, {0} };
+
+ err = gcry_sexp_extract_param (s_sig, "sig-val",
+ "&'hash-algo''salt-length'",
+ ioarray+0, ioarray+1, NULL);
+ if (err)
+ {
+ gcry_sexp_release (s_sig);
+ log_error ("extracting params from PSS failed: %s\n",
+ gpg_strerror (err));
+ return err;
+ }
+ algo = hash_algo_from_buffer (ioarray[0].data, ioarray[0].len);
+ saltlen = uint_from_buffer (ioarray[1].data, ioarray[1].len);
+ xfree (ioarray[0].data);
+ xfree (ioarray[1].data);
+ if (saltlen < 20)
+ {
+ log_error ("length of PSS salt too short\n");
+ gcry_sexp_release (s_sig);
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+ if (!algo)
+ {
+ gcry_sexp_release (s_sig);
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+ /* Add some restrictions; see ../sm/certcheck.c for details. */
+ switch (algo)
+ {
+ case GCRY_MD_SHA1:
+ case GCRY_MD_SHA256:
+ case GCRY_MD_SHA384:
+ case GCRY_MD_SHA512:
+ case GCRY_MD_SHA3_256:
+ case GCRY_MD_SHA3_384:
+ case GCRY_MD_SHA3_512:
+ break;
+ default:
+ log_error ("PSS hash algorithm '%s' rejected\n",
+ gcry_md_algo_name (algo));
+ gcry_sexp_release (s_sig);
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+
+ if (gcry_md_get_algo_dlen (algo) != saltlen)
+ {
+ log_error ("PSS hash algorithm '%s' rejected due to salt length %u\n",
+ gcry_md_algo_name (algo), saltlen);
+ gcry_sexp_release (s_sig);
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
}
- err = gcry_sexp_sscan ( &s_sig, NULL, p, n);
- ksba_free (p);
+ algo_name = hash_algo_to_string (algo);
+ err = gcry_md_open (&md, algo, 0);
if (err)
{
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (err));
+ log_error ("md_open failed: %s\n", gpg_strerror (err));
+ gcry_sexp_release (s_sig);
+ return err;
+ }
+ if (DBG_HASHING)
+ gcry_md_debug (md, "hash.cert");
+
+ err = ksba_cert_hash (cert, 1, HASH_FNC, md);
+ if (err)
+ {
+ log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (err));
gcry_md_close (md);
+ gcry_sexp_release (s_sig);
return err;
}
+ gcry_md_final (md);
/* Get the public key from the issuer certificate. */
p = ksba_cert_get_public_key (issuer_cert);
@@ -994,10 +1091,22 @@ check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
* S_SIG - Signature value as given in the certificate.
* MD - Finalized hash context with hash of the certificate.
* ALGO_NAME - Lowercase hash algorithm name
+ * SALTLEN - Salt length for rsaPSS.
*/
digestlen = gcry_md_get_algo_dlen (algo);
digest = gcry_md_read (md, algo);
- if (pk_algo_from_sexp (s_pkey) == GCRY_PK_DSA)
+ if (use_pss)
+ {
+ err = gcry_sexp_build (&s_hash, NULL,
+ "(data (flags pss)"
+ "(hash %s %b)"
+ "(salt-length %u))",
+ algo_name,
+ (int)digestlen,
+ digest,
+ saltlen);
+ }
+ else if (pk_algo_from_sexp (s_pkey) == GCRY_PK_DSA)
{
/* NB.: We support only SHA-1 here because we had problems back
* then to get test data for DSA-2. Meanwhile DSA has been
@@ -1010,19 +1119,17 @@ check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
gcry_sexp_release (s_pkey);
return gpg_error (GPG_ERR_INTERNAL);
}
- if ( gcry_sexp_build (&s_hash, NULL, "(data(flags raw)(value %b))",
- (int)digestlen, digest) )
- BUG ();
+ err = gcry_sexp_build (&s_hash, NULL, "(data(flags raw)(value %b))",
+ (int)digestlen, digest);
}
else /* Not DSA - we assume RSA */
{
- if ( gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))",
- algo_name, (int)digestlen, digest) )
- BUG ();
-
+ err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))",
+ algo_name, (int)digestlen, digest);
}
- err = gcry_pk_verify (s_sig, s_hash, s_pkey);
+ if (!err)
+ err = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_X509)
log_debug ("gcry_pk_verify: %s\n", gpg_strerror (err));
gcry_md_close (md);
diff --git a/doc/DETAILS b/doc/DETAILS
index 883fe03..acca242 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -545,9 +545,10 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
actual key used for descryption. <fpr2> is the fingerprint of the
primary key. <otrust> is the letter with the ownertrust; this is
in general a 'u' which stands for ultimately trusted.
-*** DECRYPTION_INFO <mdc_method> <sym_algo>
+*** DECRYPTION_INFO <mdc_method> <sym_algo> [<aead_algo>]
Print information about the symmetric encryption algorithm and the
MDC method. This will be emitted even if the decryption fails.
+ For an AEAD algorithm AEAD_ALGO is not 0.
*** DECRYPTION_FAILED
The symmetric decryption failed - one reason could be a wrong
@@ -1138,6 +1139,38 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
*** BEGIN_STREAM, END_STREAM
Used to issued by the experimental pipemode.
+** Inter-component codes
+ Status codes are also used between the components of the GnuPG
+ system via the Assuan S lines. Some of them are documented here:
+
+*** PUBKEY_INFO <n> <ubid>
+ The type of the public key in the following D-lines or
+ communicated via a pipe. <n> is the value of =enum pubkey_types=
+ and <ubid> the Unique Blob ID (UBID) which is the fingerprint of
+ the primary key truncated to 20 octets and formatted in hex. Note
+ that the keyboxd SEARCH command can be used to lookup the public
+ key using the <ubid> prefixed with a caret (^).
+
+*** KEYPAIRINFO <grip> <keyref> [<usage>] [<keytime>]
+
+ This status is emitted by scdaemon and gpg-agent to convey brief
+ information about keypairs stored on tokens. <grip> is the
+ hexified keygrip of the key or, if no key is stored, an "X".
+ <keyref> is the ID of a card's key; for example "OPENPGP.2" for
+ the second key slot of an OpenPGP card. <usage> is optional and
+ returns technically possible key usages, this is a string of
+ single letters describing the usage ('c' for certify, 'e' for
+ encryption, 's' for signing, 'a' for authentication). A '-' can be
+ used to tell that usage flags are not conveyed. <keytime> is used
+ by OpenPGP cards for the stored key creation time. A '-' means no
+ info available. The format is the usual ISO string are a number
+ with the seconds since Epoch.
+*** MANUFACTURER <n> [<string>]
+
+ This status returns the Manufactorer ID as the unsigned number N.
+ For OpenPGP this is weel defined; for other cards this is 0. The
+ name of the manufacturer is also given as <string>; spaces are not
+ escaped. For PKCS#15 cards <string> is TokenInfo.manufactorerID.
* Format of the --attribute-fd output
diff --git a/doc/Makefile.am b/doc/Makefile.am
index d47d83e..ca13bcf 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -182,6 +182,8 @@ defsincdate: $(gnupg_TEXINFOS)
if test -e $(top_srcdir)/.git; then \
(cd $(srcdir) && git log -1 --format='%ct' \
-- $(gnupg_TEXINFOS) 2>/dev/null) >>defsincdate; \
+ elif test x"$SOURCE_DATE_EPOCH" != x; then \
+ echo "$SOURCE_DATE_EPOCH" >>defsincdate ; \
fi
defs.inc : defsincdate Makefile mkdefsinc
diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi
index eb30368..1c329a7 100644
--- a/doc/gpgsm.texi
+++ b/doc/gpgsm.texi
@@ -409,9 +409,14 @@ change it.
@itemx --disable-crl-checks
@opindex enable-crl-checks
@opindex disable-crl-checks
-By default the @acronym{CRL} checks are enabled and the DirMngr is used
-to check for revoked certificates. The disable option is most useful
-with an off-line network connection to suppress this check.
+By default the @acronym{CRL} checks are enabled and the DirMngr is
+used to check for revoked certificates. The disable option is most
+useful with an off-line network connection to suppress this check and
+also to avoid that new certificates introduce a web bug by including a
+certificate specific CRL DP. The disable option also disables an
+issuer certificate lookup via the authorityInfoAccess property of the
+certificate; the @option{--enable-issuer-key-retrieve} can be used
+to make use of that property anyway.
@item --enable-trusted-cert-crl-check
@itemx --disable-trusted-cert-crl-check
@@ -438,6 +443,14 @@ hold in the keybox. The suggested way of doing this is by using it
along with the option @option{--with-validation} for a key listing
command. This option should not be used in a configuration file.
+@item --enable-issuer-based-crl-check
+@opindex enable-issuer-based-crl-check
+Run a CRL check even for certificates which do not have any CRL
+distribution point. This requires that a suitable LDAP server has
+been configured in Dirmngr and that the CRL can be found using the
+issuer. This option reverts to what GnuPG did up to version 2.2.20.
+This option is in general not useful.
+
@item --enable-ocsp
@itemx --disable-ocsp
@opindex enable-ocsp
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 574f6ca..7c08c9b 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -484,6 +484,7 @@ agent_release_card_info (struct agent_card_info_s *info)
return;
xfree (info->reader); info->reader = NULL;
+ xfree (info->manufacturer_name); info->manufacturer_name = NULL;
xfree (info->serialno); info->serialno = NULL;
xfree (info->apptype); info->apptype = NULL;
xfree (info->disp_name); info->disp_name = NULL;
@@ -507,6 +508,7 @@ learn_status_cb (void *opaque, const char *line)
const char *keyword = line;
int keywordlen;
int i;
+ char *endp;
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
;
@@ -706,6 +708,16 @@ learn_status_cb (void *opaque, const char *line)
xfree (parm->private_do[no]);
parm->private_do[no] = unescape_status_string (line);
}
+ else if (keywordlen == 12 && !memcmp (keyword, "MANUFACTURER", 12))
+ {
+ xfree (parm->manufacturer_name);
+ parm->manufacturer_name = NULL;
+ parm->manufacturer_id = strtoul (line, &endp, 0);
+ while (endp && spacep (endp))
+ endp++;
+ if (endp && *endp)
+ parm->manufacturer_name = xstrdup (endp);
+ }
else if (keywordlen == 3 && !memcmp (keyword, "KDF", 3))
{
unsigned char *data = unescape_status_string (line);
@@ -1518,13 +1530,15 @@ agent_scd_checkpin (const char *serialno)
/* Note: All strings shall be UTF-8. On success the caller needs to
free the string stored at R_PASSPHRASE. On error NULL will be
- stored at R_PASSPHRASE and an appropriate fpf error code
- returned. */
+ stored at R_PASSPHRASE and an appropriate error code returned.
+ Only called from passphrase.c:passphrase_get - see there for more
+ comments on this ugly API. */
gpg_error_t
agent_get_passphrase (const char *cache_id,
const char *err_msg,
const char *prompt,
const char *desc_msg,
+ int newsymkey,
int repeat,
int check,
char **r_passphrase)
@@ -1537,6 +1551,7 @@ agent_get_passphrase (const char *cache_id,
char *arg4 = NULL;
membuf_t data;
struct default_inq_parm_s dfltparm;
+ int have_newsymkey;
memset (&dfltparm, 0, sizeof dfltparm);
@@ -1552,6 +1567,10 @@ agent_get_passphrase (const char *cache_id,
"GETINFO cmd_has_option GET_PASSPHRASE repeat",
NULL, NULL, NULL, NULL, NULL, NULL))
return gpg_error (GPG_ERR_NOT_SUPPORTED);
+ have_newsymkey = !(assuan_transact
+ (agent_ctx,
+ "GETINFO cmd_has_option GET_PASSPHRASE newsymkey",
+ NULL, NULL, NULL, NULL, NULL, NULL));
if (cache_id && *cache_id)
if (!(arg1 = percent_plus_escape (cache_id)))
@@ -1566,10 +1585,14 @@ agent_get_passphrase (const char *cache_id,
if (!(arg4 = percent_plus_escape (desc_msg)))
goto no_mem;
+ /* CHECK && REPEAT or NEWSYMKEY is here an indication that a new
+ * passphrase for symmetric encryption is requested; if the agent
+ * supports this we enable the modern API by also passing --newsymkey. */
snprintf (line, DIM(line),
- "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s",
+ "GET_PASSPHRASE --data --repeat=%d%s%s -- %s %s %s %s",
repeat,
- check? " --check --qualitybar":"",
+ ((repeat && check) || newsymkey)? " --check":"",
+ (have_newsymkey && newsymkey)? " --newsymkey":"",
arg1? arg1:"X",
arg2? arg2:"X",
arg3? arg3:"X",
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 94ca154..784ed5c 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -32,6 +32,8 @@ struct agent_card_info_s
int error; /* private. */
char *reader; /* Reader information. */
char *apptype; /* Malloced application type string. */
+ unsigned int manufacturer_id;
+ char *manufacturer_name; /* malloced. */
char *serialno; /* malloced hex string. */
char *disp_name; /* malloced. */
char *disp_lang; /* malloced. */
@@ -133,6 +135,7 @@ gpg_error_t agent_get_passphrase (const char *cache_id,
const char *err_msg,
const char *prompt,
const char *desc_msg,
+ int newsymkey,
int repeat,
int check,
char **r_passphrase);
diff --git a/g10/card-util.c b/g10/card-util.c
index 3aaea84..00b64b3 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -192,46 +192,6 @@ change_pin (int unblock_v2, int allow_admin)
agent_release_card_info (&info);
}
-static const char *
-get_manufacturer (unsigned int no)
-{
- /* Note: Make sure that there is no colon or linefeed in the string. */
- switch (no)
- {
- case 0x0001: return "PPC Card Systems";
- case 0x0002: return "Prism";
- case 0x0003: return "OpenFortress";
- case 0x0004: return "Wewid";
- case 0x0005: return "ZeitControl";
- case 0x0006: return "Yubico";
- case 0x0007: return "OpenKMS";
- case 0x0008: return "LogoEmail";
- case 0x0009: return "Fidesmo";
- case 0x000A: return "Dangerous Things";
- case 0x000B: return "Feitian Technologies";
-
- case 0x002A: return "Magrathea";
- case 0x0042: return "GnuPG e.V.";
-
- case 0x1337: return "Warsaw Hackerspace";
- case 0x2342: return "warpzone"; /* hackerspace Muenster. */
- case 0x4354: return "Confidential Technologies"; /* cotech.de */
- case 0x5443: return "TIF-IT e.V.";
- case 0x63AF: return "Trustica";
- case 0xBA53: return "c-base e.V.";
- case 0xBD0E: return "Paranoidlabs";
- case 0xF517: return "FSIJ";
- case 0xF5EC: return "F-Secure";
-
- /* 0x0000 and 0xFFFF are defined as test cards per spec,
- 0xFF00 to 0xFFFE are assigned for use with randomly created
- serial numbers. */
- case 0x0000:
- case 0xffff: return "test card";
- default: return (no & 0xff00) == 0xff00? "unmanaged S/N range":"unknown";
- }
-}
-
static void
print_sha1_fpr (estream_t fp, const unsigned char *fpr)
@@ -393,6 +353,7 @@ current_card_status (ctrl_t ctrl, estream_t fp,
unsigned int uval;
const unsigned char *thefpr;
int i;
+ char *pesc;
if (serialno && serialnobuflen)
*serialno = 0;
@@ -479,7 +440,10 @@ current_card_status (ctrl_t ctrl, estream_t fp,
{
es_fprintf (fp, "version:%.4s:\n", info.serialno+12);
uval = xtoi_2(info.serialno+16)*256 + xtoi_2 (info.serialno+18);
- es_fprintf (fp, "vendor:%04x:%s:\n", uval, get_manufacturer (uval));
+ pesc = (info.manufacturer_name
+ ? percent_escape (info.manufacturer_name, NULL) : NULL);
+ es_fprintf (fp, "vendor:%04x:%s:\n", uval, pesc? pesc:"");
+ xfree (pesc);
es_fprintf (fp, "serial:%.8s:\n", info.serialno+20);
print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
@@ -572,8 +536,7 @@ current_card_status (ctrl_t ctrl, estream_t fp,
info.serialno[14] == '0'?"":info.serialno+14,
info.serialno[15]);
tty_fprintf (fp, "Manufacturer .....: %s\n",
- get_manufacturer (xtoi_2(info.serialno+16)*256
- + xtoi_2 (info.serialno+18)));
+ info.manufacturer_name? info.manufacturer_name : "?");
tty_fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20);
print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
index 736534d..2793885 100644
--- a/g10/decrypt-data.c
+++ b/g10/decrypt-data.c
@@ -1,6 +1,7 @@
/* decrypt-data.c - Decrypt an encrypted data packet
- * Copyright (C) 1998, 1999, 2000, 2001, 2005,
- * 2006, 2009 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2001, 2005-2006, 2009 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2001, 2005-2006, 2009, 2018 Werner Koch
+ * Copyright (C) 2020 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -16,6 +17,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <config.h>
@@ -32,22 +34,71 @@
#include "../common/compliance.h"
+static int aead_decode_filter (void *opaque, int control, iobuf_t a,
+ byte *buf, size_t *ret_len);
static int mdc_decode_filter ( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
static int decode_filter ( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
-typedef struct decode_filter_context_s
+/* Our context object. */
+struct decode_filter_context_s
{
+ /* Recounter (max value is 2). We need it because we do not know
+ * whether the iobuf or the outer control code frees this object
+ * first. */
+ int refcount;
+
+ /* The cipher handle. */
gcry_cipher_hd_t cipher_hd;
+
+ /* The hash handle for use in MDC mode. */
gcry_md_hd_t mdc_hash;
- char defer[22];
- int defer_filled;
- int eof_seen;
- int refcount;
- int partial; /* Working on a partial length packet. */
- size_t length; /* If !partial: Remaining bytes in the packet. */
-} *decode_filter_ctx_t;
+
+ /* The start IV for AEAD encryption. */
+ byte startiv[16];
+
+ /* The holdback buffer and its used length. For AEAD we need 32+1
+ * bytes but we use 48 byte. For MDC we need 22 bytes; here
+ * holdbacklen will either 0 or 22. */
+ char holdback[48];
+ unsigned int holdbacklen;
+
+ /* Working on a partial length packet. */
+ unsigned int partial : 1;
+
+ /* EOF indicator with these true values:
+ * 1 = normal EOF
+ * 2 = premature EOF (tag or hash incomplete)
+ * 3 = premature EOF (general) */
+ unsigned int eof_seen : 2;
+
+ /* The actually used cipher algo for AEAD. */
+ byte cipher_algo;
+
+ /* The AEAD algo. */
+ byte aead_algo;
+
+ /* The encoded chunk byte for AEAD. */
+ byte chunkbyte;
+
+ /* The decoded CHUNKBYTE. */
+ uint64_t chunksize;
+
+ /* The chunk index for AEAD. */
+ uint64_t chunkindex;
+
+ /* The number of bytes in the current chunk. */
+ uint64_t chunklen;
+
+ /* The total count of decrypted plaintext octets. */
+ uint64_t total;
+
+ /* Remaining bytes in the packet according to the packet header.
+ * Not used if PARTIAL is true. */
+ size_t length;
+};
+typedef struct decode_filter_context_s *decode_filter_ctx_t;
/* Helper to release the decode context. */
@@ -69,6 +120,99 @@ release_dfx_context (decode_filter_ctx_t dfx)
}
+/* Set the nonce and the additional data for the current chunk. This
+ * also reset the decryption machinery so that the handle can be
+ * used for a new chunk. If FINAL is set the final AEAD chunk is
+ * processed. */
+static gpg_error_t
+aead_set_nonce_and_ad (decode_filter_ctx_t dfx, int final)
+{
+ gpg_error_t err;
+ unsigned char ad[21];
+ unsigned char nonce[16];
+ int i;
+
+ switch (dfx->aead_algo)
+ {
+ case AEAD_ALGO_OCB:
+ memcpy (nonce, dfx->startiv, 15);
+ i = 7;
+ break;
+
+ case AEAD_ALGO_EAX:
+ memcpy (nonce, dfx->startiv, 16);
+ i = 8;
+ break;
+
+ default:
+ BUG ();
+ }
+ nonce[i++] ^= dfx->chunkindex >> 56;
+ nonce[i++] ^= dfx->chunkindex >> 48;
+ nonce[i++] ^= dfx->chunkindex >> 40;
+ nonce[i++] ^= dfx->chunkindex >> 32;
+ nonce[i++] ^= dfx->chunkindex >> 24;
+ nonce[i++] ^= dfx->chunkindex >> 16;
+ nonce[i++] ^= dfx->chunkindex >> 8;
+ nonce[i++] ^= dfx->chunkindex;
+
+ if (DBG_CRYPTO)
+ log_printhex (nonce, i, "nonce:");
+ err = gcry_cipher_setiv (dfx->cipher_hd, nonce, i);
+ if (err)
+ return err;
+
+ ad[0] = (0xc0 | PKT_ENCRYPTED_AEAD);
+ ad[1] = 1;
+ ad[2] = dfx->cipher_algo;
+ ad[3] = dfx->aead_algo;
+ ad[4] = dfx->chunkbyte;
+ ad[5] = dfx->chunkindex >> 56;
+ ad[6] = dfx->chunkindex >> 48;
+ ad[7] = dfx->chunkindex >> 40;
+ ad[8] = dfx->chunkindex >> 32;
+ ad[9] = dfx->chunkindex >> 24;
+ ad[10]= dfx->chunkindex >> 16;
+ ad[11]= dfx->chunkindex >> 8;
+ ad[12]= dfx->chunkindex;
+ if (final)
+ {
+ ad[13] = dfx->total >> 56;
+ ad[14] = dfx->total >> 48;
+ ad[15] = dfx->total >> 40;
+ ad[16] = dfx->total >> 32;
+ ad[17] = dfx->total >> 24;
+ ad[18] = dfx->total >> 16;
+ ad[19] = dfx->total >> 8;
+ ad[20] = dfx->total;
+ }
+ if (DBG_CRYPTO)
+ log_printhex (ad, final? 21 : 13, "authdata:");
+ return gcry_cipher_authenticate (dfx->cipher_hd, ad, final? 21 : 13);
+}
+
+
+/* Helper to check the 16 byte tag in TAGBUF. The FINAL flag is only
+ * for debug messages. */
+static gpg_error_t
+aead_checktag (decode_filter_ctx_t dfx, int final, const void *tagbuf)
+{
+ gpg_error_t err;
+
+ if (DBG_FILTER)
+ log_printhex (tagbuf, 16, "tag:");
+ err = gcry_cipher_checktag (dfx->cipher_hd, tagbuf, 16);
+ if (err)
+ {
+ log_error ("gcry_cipher_checktag%s failed: %s\n",
+ final? " (final)":"", gpg_strerror (err));
+ return err;
+ }
+ if (DBG_FILTER)
+ log_debug ("%stag is valid\n", final?"final ":"");
+ return 0;
+}
+
/****************
* Decrypt the data, specified by ED with the key DEK.
@@ -77,6 +221,8 @@ int
decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
{
decode_filter_ctx_t dfx;
+ enum gcry_cipher_modes ciphermode;
+ unsigned int startivlen;
byte *p;
int rc=0, c, i;
byte temp[32];
@@ -98,9 +244,18 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
dek->algo_info_printed = 1;
}
+ if (ed->aead_algo)
+ {
+ rc = openpgp_aead_algo_info (ed->aead_algo, &ciphermode, &startivlen);
+ if (rc)
+ goto leave;
+ log_assert (startivlen <= sizeof dfx->startiv);
+ }
+ else
+ ciphermode = GCRY_CIPHER_MODE_CFB;
+
/* Check compliance. */
- if (! gnupg_cipher_is_allowed (opt.compliance, 0, dek->algo,
- GCRY_CIPHER_MODE_CFB))
+ if (!gnupg_cipher_is_allowed (opt.compliance, 0, dek->algo, ciphermode))
{
log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
openpgp_cipher_algo_name (dek->algo),
@@ -109,12 +264,8 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
goto leave;
}
- {
- char buf[20];
-
- snprintf (buf, sizeof buf, "%d %d", ed->mdc_method, dek->algo);
- write_status_text (STATUS_DECRYPTION_INFO, buf);
- }
+ write_status_printf (STATUS_DECRYPTION_INFO, "%d %d %d",
+ ed->mdc_method, dek->algo, 0);
if (opt.show_session_key)
{
@@ -139,95 +290,181 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
blocksize = openpgp_cipher_get_algo_blklen (dek->algo);
if ( !blocksize || blocksize > 16 )
log_fatal ("unsupported blocksize %u\n", blocksize );
- nprefix = blocksize;
- if ( ed->len && ed->len < (nprefix+2) )
- {
- /* An invalid message. We can't check that during parsing
- because we may not know the used cipher then. */
- rc = gpg_error (GPG_ERR_INV_PACKET);
- goto leave;
- }
- if ( ed->mdc_method )
+ if (ed->aead_algo)
{
- if (gcry_md_open (&dfx->mdc_hash, ed->mdc_method, 0 ))
- BUG ();
- if ( DBG_HASHING )
- gcry_md_debug (dfx->mdc_hash, "checkmdc");
- }
+ if (blocksize != 16)
+ {
+ rc = gpg_error (GPG_ERR_CIPHER_ALGO);
+ goto leave;
+ }
- rc = openpgp_cipher_open (&dfx->cipher_hd, dek->algo,
- GCRY_CIPHER_MODE_CFB,
- (GCRY_CIPHER_SECURE
- | ((ed->mdc_method || dek->algo >= 100)?
- 0 : GCRY_CIPHER_ENABLE_SYNC)));
- if (rc)
- {
- /* We should never get an error here cause we already checked
- * that the algorithm is available. */
- BUG();
- }
+ if (ed->chunkbyte > 56)
+ {
+ log_error ("invalid AEAD chunkbyte %u\n", ed->chunkbyte);
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
+ }
+ /* Read the Start-IV. */
+ if (ed->len)
+ {
+ for (i=0; i < startivlen && ed->len; i++, ed->len--)
+ {
+ if ((c=iobuf_get (ed->buf)) == -1)
+ break;
+ dfx->startiv[i] = c;
+ }
+ }
+ else
+ {
+ for (i=0; i < startivlen; i++ )
+ if ( (c=iobuf_get (ed->buf)) == -1 )
+ break;
+ else
+ dfx->startiv[i] = c;
+ }
+ if (i != startivlen)
+ {
+ log_error ("Start-IV in AEAD packet too short (%d/%u)\n",
+ i, startivlen);
+ rc = gpg_error (GPG_ERR_TOO_SHORT);
+ goto leave;
+ }
+
+ dfx->cipher_algo = ed->cipher_algo;
+ dfx->aead_algo = ed->aead_algo;
+ dfx->chunkbyte = ed->chunkbyte;
+ dfx->chunksize = (uint64_t)1 << (dfx->chunkbyte + 6);
+
+ if (dek->algo != dfx->cipher_algo)
+ log_info ("Note: different cipher algorithms used (%s/%s)\n",
+ openpgp_cipher_algo_name (dek->algo),
+ openpgp_cipher_algo_name (dfx->cipher_algo));
+
+ rc = openpgp_cipher_open (&dfx->cipher_hd,
+ dfx->cipher_algo,
+ ciphermode,
+ GCRY_CIPHER_SECURE);
+ if (rc)
+ goto leave; /* Should never happen. */
+
+ if (DBG_CRYPTO)
+ log_printhex (dek->key, dek->keylen, "thekey:");
+ rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
+ if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY)
+ {
+ log_info (_("WARNING: message was encrypted with"
+ " a weak key in the symmetric cipher.\n"));
+ rc = 0;
+ }
+ else if (rc)
+ {
+ log_error("key setup failed: %s\n", gpg_strerror (rc));
+ goto leave;
+ }
+
+ if (!ed->buf)
+ {
+ log_error(_("problem handling encrypted packet\n"));
+ goto leave;
+ }
- /* log_hexdump( "thekey", dek->key, dek->keylen );*/
- rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
- if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
- {
- log_info(_("WARNING: message was encrypted with"
- " a weak key in the symmetric cipher.\n"));
- rc=0;
}
- else if( rc )
+ else /* CFB encryption. */
{
- log_error("key setup failed: %s\n", gpg_strerror (rc) );
- goto leave;
- }
+ nprefix = blocksize;
+ if ( ed->len && ed->len < (nprefix+2) )
+ {
+ /* An invalid message. We can't check that during parsing
+ * because we may not know the used cipher then. */
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
+ }
- if (!ed->buf)
- {
- log_error(_("problem handling encrypted packet\n"));
- goto leave;
- }
+ if ( ed->mdc_method )
+ {
+ if (gcry_md_open (&dfx->mdc_hash, ed->mdc_method, 0 ))
+ BUG ();
+ if ( DBG_HASHING )
+ gcry_md_debug (dfx->mdc_hash, "checkmdc");
+ }
+
+ rc = openpgp_cipher_open (&dfx->cipher_hd, dek->algo,
+ GCRY_CIPHER_MODE_CFB,
+ (GCRY_CIPHER_SECURE
+ | ((ed->mdc_method || dek->algo >= 100)?
+ 0 : GCRY_CIPHER_ENABLE_SYNC)));
+ if (rc)
+ {
+ /* We should never get an error here cause we already checked
+ * that the algorithm is available. */
+ BUG();
+ }
- gcry_cipher_setiv (dfx->cipher_hd, NULL, 0);
- if ( ed->len )
- {
- for (i=0; i < (nprefix+2) && ed->len; i++, ed->len-- )
+ /* log_hexdump( "thekey", dek->key, dek->keylen );*/
+ rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
+ if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
{
- if ( (c=iobuf_get(ed->buf)) == -1 )
- break;
- else
- temp[i] = c;
+ log_info (_("WARNING: message was encrypted with"
+ " a weak key in the symmetric cipher.\n"));
+ rc = 0;
+ }
+ else if (rc)
+ {
+ log_error("key setup failed: %s\n", gpg_strerror (rc) );
+ goto leave;
}
- }
- else
- {
- for (i=0; i < (nprefix+2); i++ )
- if ( (c=iobuf_get(ed->buf)) == -1 )
- break;
- else
- temp[i] = c;
- }
- gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
- gcry_cipher_sync (dfx->cipher_hd);
- p = temp;
- /* log_hexdump( "prefix", temp, nprefix+2 ); */
- if (dek->symmetric
- && (p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1]) )
- {
- rc = gpg_error (GPG_ERR_BAD_KEY);
- goto leave;
- }
+ if (!ed->buf)
+ {
+ log_error (_("problem handling encrypted packet\n"));
+ goto leave;
+ }
- if ( dfx->mdc_hash )
- gcry_md_write (dfx->mdc_hash, temp, nprefix+2);
+ gcry_cipher_setiv (dfx->cipher_hd, NULL, 0);
+
+ if ( ed->len )
+ {
+ for (i=0; i < (nprefix+2) && ed->len; i++, ed->len-- )
+ {
+ if ( (c=iobuf_get(ed->buf)) == -1 )
+ break;
+ else
+ temp[i] = c;
+ }
+ }
+ else
+ {
+ for (i=0; i < (nprefix+2); i++ )
+ if ( (c=iobuf_get(ed->buf)) == -1 )
+ break;
+ else
+ temp[i] = c;
+ }
+
+ gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
+ gcry_cipher_sync (dfx->cipher_hd);
+ p = temp;
+ /* log_hexdump( "prefix", temp, nprefix+2 ); */
+ if (dek->symmetric
+ && (p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1]) )
+ {
+ rc = gpg_error (GPG_ERR_BAD_KEY);
+ goto leave;
+ }
+
+ if ( dfx->mdc_hash )
+ gcry_md_write (dfx->mdc_hash, temp, nprefix+2);
+ }
dfx->refcount++;
- dfx->partial = ed->is_partial;
+ dfx->partial = !!ed->is_partial;
dfx->length = ed->len;
- if ( ed->mdc_method )
+ if (ed->aead_algo)
+ iobuf_push_filter ( ed->buf, aead_decode_filter, dfx );
+ else if (ed->mdc_method)
iobuf_push_filter ( ed->buf, mdc_decode_filter, dfx );
else
iobuf_push_filter ( ed->buf, decode_filter, dfx );
@@ -287,26 +524,359 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
log_assert (dfx->cipher_hd);
log_assert (dfx->mdc_hash);
- gcry_cipher_decrypt (dfx->cipher_hd, dfx->defer, 22, NULL, 0);
- gcry_md_write (dfx->mdc_hash, dfx->defer, 2);
+ gcry_cipher_decrypt (dfx->cipher_hd, dfx->holdback, 22, NULL, 0);
+ gcry_md_write (dfx->mdc_hash, dfx->holdback, 2);
gcry_md_final (dfx->mdc_hash);
- if ( dfx->defer[0] != '\xd3'
- || dfx->defer[1] != '\x14'
+ if ( dfx->holdback[0] != '\xd3'
+ || dfx->holdback[1] != '\x14'
|| datalen != 20
- || memcmp (gcry_md_read (dfx->mdc_hash, 0), dfx->defer+2, datalen))
+ || memcmp (gcry_md_read (dfx->mdc_hash, 0), dfx->holdback+2, datalen))
rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
- /* log_printhex("MDC message:", dfx->defer, 22); */
- /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */
+ /* log_printhex(dfx->holdback, 22, "MDC message:"); */
+ /* log_printhex(gcry_md_read (dfx->mdc_hash,0), datalen, "MDC calc:"); */
}
-
leave:
release_dfx_context (dfx);
return rc;
}
+/* Fill BUFFER with up to NBYTES-OFFSET from STREAM utilizing
+ * information from the context DFX. Returns the new offset which is
+ * the number of bytes read plus the original offset. On EOF the
+ * respective flag in DFX is set. */
+static size_t
+fill_buffer (decode_filter_ctx_t dfx, iobuf_t stream,
+ byte *buffer, size_t nbytes, size_t offset)
+{
+ size_t nread = offset;
+ size_t curr;
+ int ret;
+
+ if (dfx->partial)
+ {
+ while (nread < nbytes)
+ {
+ curr = nbytes - nread;
+
+ ret = iobuf_read (stream, &buffer[nread], curr);
+ if (ret == -1)
+ {
+ dfx->eof_seen = 1; /* Normal EOF. */
+ break;
+ }
+
+ nread += ret;
+ }
+ }
+ else
+ {
+ while (nread < nbytes && dfx->length)
+ {
+ curr = nbytes - nread;
+ if (curr > dfx->length)
+ curr = dfx->length;
+
+ ret = iobuf_read (stream, &buffer[nread], curr);
+ if (ret == -1)
+ {
+ dfx->eof_seen = 3; /* Premature EOF. */
+ break;
+ }
+
+ nread += ret;
+ dfx->length -= ret;
+ }
+ if (!dfx->length)
+ dfx->eof_seen = 1; /* Normal EOF. */
+ }
+
+ return nread;
+}
+
+
+/* The core of the AEAD decryption. This is the underflow function of
+ * the aead_decode_filter. */
+static gpg_error_t
+aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
+{
+ const size_t size = *ret_len; /* The allocated size of BUF. */
+ gpg_error_t err;
+ size_t totallen = 0; /* The number of bytes to return on success or EOF. */
+ size_t off = 0; /* The offset into the buffer. */
+ size_t len; /* The current number of bytes in BUF+OFF. */
+
+ log_assert (size > 48); /* Our code requires at least this size. */
+
+ /* Copy the rest from the last call of this function into BUF. */
+ len = dfx->holdbacklen;
+ dfx->holdbacklen = 0;
+ memcpy (buf, dfx->holdback, len);
+
+ if (DBG_FILTER)
+ log_debug ("aead_underflow: size=%zu len=%zu%s%s\n", size, len,
+ dfx->partial? " partial":"", dfx->eof_seen? " eof":"");
+
+ /* Read and fill up BUF. We need to watch out for an EOF so that we
+ * can detect the last chunk which is commonly shorter than the
+ * chunksize. After the last data byte from the last chunk 32 more
+ * bytes are expected for the last chunk's tag and the following
+ * final chunk's tag. To detect the EOF we need to try reading at least
+ * one further byte; however we try to read 16 extra bytes to avoid
+ * single byte reads in some lower layers. The outcome is that we
+ * have up to 48 extra extra octets which we will later put into the
+ * holdback buffer for the next invocation (which handles the EOF
+ * case). */
+ len = fill_buffer (dfx, a, buf, size, len);
+ if (len < 32)
+ {
+ /* Not enough data for the last two tags. */
+ err = gpg_error (GPG_ERR_TRUNCATED);
+ goto leave;
+ }
+ if (dfx->eof_seen)
+ {
+ /* If have seen an EOF we copy only the last two auth tags into
+ * the holdback buffer. */
+ dfx->holdbacklen = 32;
+ memcpy (dfx->holdback, buf+len-32, 32);
+ len -= 32;
+ }
+ else
+ {
+ /* If have not seen an EOF we copy the entire extra 48 bytes
+ * into the holdback buffer for processing at the next call of
+ * this function. */
+ dfx->holdbacklen = len > 48? 48 : len;
+ memcpy (dfx->holdback, buf+len-dfx->holdbacklen, dfx->holdbacklen);
+ len -= dfx->holdbacklen;
+ }
+ /* log_printhex (dfx->holdback, dfx->holdbacklen, "holdback:"); */
+
+ /* Decrypt the buffer. This first requires a loop to handle the
+ * case when a chunk ends within the buffer. */
+ if (DBG_FILTER)
+ log_debug ("decrypt: chunklen=%ju total=%ju size=%zu len=%zu%s\n",
+ dfx->chunklen, dfx->total, size, len,
+ dfx->eof_seen? " eof":"");
+
+ while (len && dfx->chunklen + len >= dfx->chunksize)
+ {
+ size_t n = dfx->chunksize - dfx->chunklen;
+ byte tagbuf[16];
+
+ if (DBG_FILTER)
+ log_debug ("chunksize will be reached: n=%zu\n", n);
+
+ if (!dfx->chunklen)
+ {
+ /* First data for this chunk - prepare. */
+ err = aead_set_nonce_and_ad (dfx, 0);
+ if (err)
+ goto leave;
+ }
+
+ /* log_printhex (buf, n, "ciph:"); */
+ gcry_cipher_final (dfx->cipher_hd);
+ err = gcry_cipher_decrypt (dfx->cipher_hd, buf+off, n, NULL, 0);
+ if (err)
+ {
+ log_error ("gcry_cipher_decrypt failed (1): %s\n",
+ gpg_strerror (err));
+ goto leave;
+ }
+ /* log_printhex (buf, n, "plai:"); */
+ totallen += n;
+ dfx->chunklen += n;
+ dfx->total += n;
+ off += n;
+ len -= n;
+
+ if (DBG_FILTER)
+ log_debug ("ndecrypted: %zu (nchunk=%ju) bytes left: %zu at off=%zu\n",
+ totallen, dfx->chunklen, len, off);
+
+ /* Check the tag. */
+ if (len < 16)
+ {
+ /* The tag is not entirely in the buffer. Read the rest of
+ * the tag from the holdback buffer. Then shift the holdback
+ * buffer and fill it up again. */
+ memcpy (tagbuf, buf+off, len);
+ memcpy (tagbuf + len, dfx->holdback, 16 - len);
+ dfx->holdbacklen -= 16-len;
+ memmove (dfx->holdback, dfx->holdback + (16-len), dfx->holdbacklen);
+
+ if (dfx->eof_seen)
+ {
+ /* We should have the last chunk's tag in TAGBUF and the
+ * final tag in HOLDBACKBUF. */
+ if (len || dfx->holdbacklen != 16)
+ {
+ /* Not enough data for the last two tags. */
+ err = gpg_error (GPG_ERR_TRUNCATED);
+ goto leave;
+ }
+ }
+ else
+ {
+ len = 0;
+ dfx->holdbacklen = fill_buffer (dfx, a, dfx->holdback, 48,
+ dfx->holdbacklen);
+ if (dfx->holdbacklen < 32)
+ {
+ /* Not enough data for the last two tags. */
+ err = gpg_error (GPG_ERR_TRUNCATED);
+ goto leave;
+ }
+ }
+ }
+ else /* We already have the full tag. */
+ {
+ memcpy (tagbuf, buf+off, 16);
+ /* Remove that tag from the output. */
+ memmove (buf + off, buf + off + 16, len - 16);
+ len -= 16;
+ }
+ err = aead_checktag (dfx, 0, tagbuf);
+ if (err)
+ goto leave;
+ dfx->chunklen = 0;
+ dfx->chunkindex++;
+
+ continue;
+ }
+
+ /* The bulk decryption of our buffer. */
+ if (len)
+ {
+ if (!dfx->chunklen)
+ {
+ /* First data for this chunk - prepare. */
+ err = aead_set_nonce_and_ad (dfx, 0);
+ if (err)
+ goto leave;
+ }
+
+ if (dfx->eof_seen)
+ {
+ /* This is the last block of the last chunk. Its length may
+ * not be a multiple of the block length. */
+ gcry_cipher_final (dfx->cipher_hd);
+ }
+ err = gcry_cipher_decrypt (dfx->cipher_hd, buf + off, len, NULL, 0);
+ if (err)
+ {
+ log_error ("gcry_cipher_decrypt failed (2): %s\n",
+ gpg_strerror (err));
+ goto leave;
+ }
+ totallen += len;
+ dfx->chunklen += len;
+ dfx->total += len;
+ if (DBG_FILTER)
+ log_debug ("ndecrypted: %zu (nchunk=%ju)\n", totallen, dfx->chunklen);
+ }
+
+ if (dfx->eof_seen)
+ {
+
+ if (dfx->chunklen)
+ {
+ if (DBG_FILTER)
+ log_debug ("eof seen: holdback has the last and final tag\n");
+ log_assert (dfx->holdbacklen >= 32);
+ err = aead_checktag (dfx, 0, dfx->holdback);
+ if (err)
+ goto leave;
+ dfx->chunklen = 0;
+ dfx->chunkindex++;
+ off = 16;
+ }
+ else
+ {
+ if (DBG_FILTER)
+ log_debug ("eof seen: holdback has the final tag\n");
+ log_assert (dfx->holdbacklen >= 16);
+ off = 0;
+ }
+
+ /* Check the final chunk. */
+ err = aead_set_nonce_and_ad (dfx, 1);
+ if (err)
+ goto leave;
+ gcry_cipher_final (dfx->cipher_hd);
+ /* Decrypt an empty string (using HOLDBACK as a dummy). */
+ err = gcry_cipher_decrypt (dfx->cipher_hd, dfx->holdback, 0, NULL, 0);
+ if (err)
+ {
+ log_error ("gcry_cipher_decrypt failed (final): %s\n",
+ gpg_strerror (err));
+ goto leave;
+ }
+ err = aead_checktag (dfx, 1, dfx->holdback+off);
+ if (err)
+ goto leave;
+ err = gpg_error (GPG_ERR_EOF);
+ }
+
+ leave:
+ if (DBG_FILTER)
+ log_debug ("aead_underflow: returning %zu (%s)\n",
+ totallen, gpg_strerror (err));
+
+ /* In case of an auth error we map the error code to the same as
+ * used by the MDC decryption. */
+ if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
+ err = gpg_error (GPG_ERR_BAD_SIGNATURE);
+
+ /* In case of an error we better wipe out the buffer than to convey
+ * partly decrypted data. */
+ if (err && gpg_err_code (err) != GPG_ERR_EOF)
+ memset (buf, 0, size);
+
+ *ret_len = totallen;
+
+ return err;
+}
+
+
+/* The IOBUF filter used to decrypt AEAD encrypted data. */
+static int
+aead_decode_filter (void *opaque, int control, IOBUF a,
+ byte *buf, size_t *ret_len)
+{
+ decode_filter_ctx_t dfx = opaque;
+ int rc = 0;
+
+ if ( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen )
+ {
+ *ret_len = 0;
+ rc = -1;
+ }
+ else if ( control == IOBUFCTRL_UNDERFLOW )
+ {
+ log_assert (a);
+
+ rc = aead_underflow (dfx, a, buf, ret_len);
+ if (gpg_err_code (rc) == GPG_ERR_EOF)
+ rc = -1; /* We need to use the old convention in the filter. */
+
+ }
+ else if ( control == IOBUFCTRL_FREE )
+ {
+ release_dfx_context (dfx);
+ }
+ else if ( control == IOBUFCTRL_DESC )
+ {
+ mem2str (buf, "aead_decode_filter", *ret_len);
+ }
+
+ return rc;
+}
+
static int
mdc_decode_filter (void *opaque, int control, IOBUF a,
@@ -315,7 +885,6 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
decode_filter_ctx_t dfx = opaque;
size_t n, size = *ret_len;
int rc = 0;
- int c;
/* Note: We need to distinguish between a partial and a fixed length
packet. The first is the usual case as created by GPG. However
@@ -336,73 +905,29 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
log_assert (size > 44); /* Our code requires at least this size. */
/* Get at least 22 bytes and put it ahead in the buffer. */
- if (dfx->partial)
- {
- for (n=22; n < 44; n++)
- {
- if ( (c = iobuf_get(a)) == -1 )
- break;
- buf[n] = c;
- }
- }
- else
- {
- for (n=22; n < 44 && dfx->length; n++, dfx->length--)
- {
- c = iobuf_get (a);
- if (c == -1)
- break; /* Premature EOF. */
- buf[n] = c;
- }
- }
+ n = fill_buffer (dfx, a, buf, 44, 22);
if (n == 44)
{
/* We have enough stuff - flush the deferred stuff. */
- if ( !dfx->defer_filled ) /* First time. */
+ if ( !dfx->holdbacklen ) /* First time. */
{
memcpy (buf, buf+22, 22);
n = 22;
}
else
{
- memcpy (buf, dfx->defer, 22);
+ memcpy (buf, dfx->holdback, 22);
}
/* Fill up the buffer. */
- if (dfx->partial)
- {
- for (; n < size; n++ )
- {
- if ( (c = iobuf_get(a)) == -1 )
- {
- dfx->eof_seen = 1; /* Normal EOF. */
- break;
- }
- buf[n] = c;
- }
- }
- else
- {
- for (; n < size && dfx->length; n++, dfx->length--)
- {
- c = iobuf_get(a);
- if (c == -1)
- {
- dfx->eof_seen = 3; /* Premature EOF. */
- break;
- }
- buf[n] = c;
- }
- if (!dfx->length)
- dfx->eof_seen = 1; /* Normal EOF. */
- }
+ n = fill_buffer (dfx, a, buf, size, n);
- /* Move the trailing 22 bytes back to the defer buffer. We
+ /* Move the trailing 22 bytes back to the holdback buffer. We
have at least 44 bytes thus a memmove is not needed. */
n -= 22;
- memcpy (dfx->defer, buf+n, 22 );
- dfx->defer_filled = 1;
+ memcpy (dfx->holdback, buf+n, 22 );
+ dfx->holdbacklen = 22;
}
- else if ( !dfx->defer_filled ) /* EOF seen but empty defer buffer. */
+ else if ( !dfx->holdbacklen ) /* EOF seen but empty holdback buffer. */
{
/* This is bad because it means an incomplete hash. */
n -= 22;
@@ -411,9 +936,9 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
}
else /* EOF seen (i.e. read less than 22 bytes). */
{
- memcpy (buf, dfx->defer, 22 );
+ memcpy (buf, dfx->holdback, 22 );
n -= 22;
- memcpy (dfx->defer, buf+n, 22 );
+ memcpy (dfx->holdback, buf+n, 22 );
dfx->eof_seen = 1; /* Normal EOF. */
}
@@ -449,7 +974,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
decode_filter_ctx_t fc = opaque;
size_t size = *ret_len;
size_t n;
- int c, rc = 0;
+ int rc = 0;
if ( control == IOBUFCTRL_UNDERFLOW && fc->eof_seen )
@@ -461,34 +986,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
{
log_assert (a);
- if (fc->partial)
- {
- for (n=0; n < size; n++ )
- {
- c = iobuf_get(a);
- if (c == -1)
- {
- fc->eof_seen = 1; /* Normal EOF. */
- break;
- }
- buf[n] = c;
- }
- }
- else
- {
- for (n=0; n < size && fc->length; n++, fc->length--)
- {
- c = iobuf_get(a);
- if (c == -1)
- {
- fc->eof_seen = 3; /* Premature EOF. */
- break;
- }
- buf[n] = c;
- }
- if (!fc->length)
- fc->eof_seen = 1; /* Normal EOF. */
- }
+ n = fill_buffer (fc, a, buf, size, 0);
if (n)
{
if (fc->cipher_hd)
diff --git a/g10/dek.h b/g10/dek.h
index 666810c..3654491 100644
--- a/g10/dek.h
+++ b/g10/dek.h
@@ -19,21 +19,31 @@
#ifndef G10_DEK_H
#define G10_DEK_H
-
typedef struct
{
/* The algorithm (e.g., CIPHER_ALGO_AES). */
int algo;
/* The length of the key (in bytes). */
int keylen;
+
/* Whether we've already printed information about this key. This
- is currently only used in decrypt_data() and only if we are in
- verbose mode. */
- int algo_info_printed;
- int use_mdc;
+ * is currently only used in decrypt_data() and only if we are in
+ * verbose mode. */
+ unsigned int algo_info_printed : 1;
+
+ /* AEAD shall be used. The value is the AEAD algo. */
+ int use_aead : 4;
+
+ /* MDC shall be used. */
+ unsigned int use_mdc : 1;
+
/* This key was read from a SK-ESK packet (see proc_symkey_enc). */
- int symmetric;
- byte key[32]; /* This is the largest used keylen (256 bit). */
+ unsigned int symmetric : 1;
+
+ /* This is the largest used keylen (256 bit). */
+ byte key[32];
+
+ /* The cacheid for the S2K. */
char s2k_cacheid[1+16+1];
} DEK;
diff --git a/g10/ecdh.c b/g10/ecdh.c
index dcb3cde..5bbea96 100644
--- a/g10/ecdh.c
+++ b/g10/ecdh.c
@@ -76,7 +76,7 @@ pk_ecdh_default_params (unsigned int qbits)
}
log_assert (i < DIM (kek_params_table));
if (DBG_CRYPTO)
- log_printhex ("ECDH KEK params are", kek_params, sizeof(kek_params) );
+ log_printhex (kek_params, sizeof(kek_params), "ECDH KEK params are");
return gcry_mpi_set_opaque (NULL, kek_params, 4 * 8);
}
@@ -159,7 +159,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
if (DBG_CRYPTO)
- log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size );
+ log_printhex (secret_x, secret_x_size, "ECDH shared secret X is:");
}
/*** We have now the shared secret bytes in secret_x. ***/
@@ -179,7 +179,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
kek_params_size = (nbits+7)/8;
if (DBG_CRYPTO)
- log_printhex ("ecdh KDF params:", kek_params, kek_params_size);
+ log_printhex (kek_params, kek_params_size, "ecdh KDF params:");
/* Expect 4 bytes 03 01 hash_alg symm_alg. */
if (kek_params_size != 4 || kek_params[0] != 3 || kek_params[1] != 1)
@@ -236,7 +236,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
}
if(DBG_CRYPTO)
- log_printhex ("ecdh KDF message params are:", message, message_size);
+ log_printhex (message, message_size, "ecdh KDF message params are:");
}
/* Derive a KEK (key wrapping key) using MESSAGE and SECRET_X. */
@@ -272,7 +272,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
/* We could have allocated more, so clean the tail before returning. */
memset (secret_x+secret_x_size, 0, old_size - secret_x_size);
if (DBG_CRYPTO)
- log_printhex ("ecdh KEK is:", secret_x, secret_x_size );
+ log_printhex (secret_x, secret_x_size, "ecdh KEK is:");
}
/* And, finally, aeswrap with key secret_x. */
@@ -338,7 +338,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
}
if (DBG_CRYPTO)
- log_printhex ("ecdh encrypting :", in, data_buf_size );
+ log_printhex (in, data_buf_size, "ecdh encrypting :");
err = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8,
in, data_buf_size);
@@ -354,7 +354,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
data_buf[0] = data_buf_size+8;
if (DBG_CRYPTO)
- log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] );
+ log_printhex (data_buf+1, data_buf[0], "ecdh encrypted to:");
result = gcry_mpi_set_opaque (NULL, data_buf, 8 * (1+data_buf[0]));
if (!result)
@@ -391,7 +391,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
data_buf_size = data_buf[0];
if (DBG_CRYPTO)
- log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size);
+ log_printhex (data_buf+1, data_buf_size, "ecdh decrypting :");
err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
data_buf_size);
@@ -407,7 +407,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
data_buf_size -= 8;
if (DBG_CRYPTO)
- log_printhex ("ecdh decrypted to :", in, data_buf_size);
+ log_printhex (in, data_buf_size, "ecdh decrypted to :");
/* Padding is removed later. */
/* if (in[data_buf_size-1] > 8 ) */
diff --git a/g10/encrypt.c b/g10/encrypt.c
index 543f1a7..42cad2b 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -110,7 +110,7 @@ encrypt_seskey (DEK *dek, DEK **seskey, byte *enckey)
/* Shall we use the MDC? Yes - unless rfc-2440 compatibility is
- * requested. */
+ * requested. Must return 1 or 0. */
int
use_mdc (pk_list_t pk_list,int algo)
{
@@ -191,18 +191,9 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
cfx.dek = NULL;
if ( mode )
{
- int canceled;
-
- s2k = xmalloc_clear( sizeof *s2k );
- s2k->mode = opt.s2k_mode;
- s2k->hash_algo = S2K_DIGEST_ALGO;
- cfx.dek = passphrase_to_dek (default_cipher_algo (), s2k, 1, 0,
- NULL, &canceled);
- if ( !cfx.dek || !cfx.dek->keylen )
+ rc = setup_symkey (&s2k, &cfx.dek);
+ if (rc)
{
- rc = gpg_error (canceled? GPG_ERR_CANCELED:GPG_ERR_INV_PASSPHRASE);
- xfree (cfx.dek);
- xfree (s2k);
iobuf_close (inp);
log_error (_("error creating passphrase: %s\n"), gpg_strerror (rc));
release_progress_context (pfx);
@@ -378,22 +369,22 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
}
-int
-setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek)
+gpg_error_t
+setup_symkey (STRING2KEY **symkey_s2k, DEK **symkey_dek)
{
int canceled;
- *symkey_s2k=xmalloc_clear(sizeof(STRING2KEY));
+ *symkey_s2k = xmalloc_clear (sizeof **symkey_s2k);
(*symkey_s2k)->mode = opt.s2k_mode;
(*symkey_s2k)->hash_algo = S2K_DIGEST_ALGO;
- *symkey_dek = passphrase_to_dek (opt.s2k_cipher_algo,
+ *symkey_dek = passphrase_to_dek (default_cipher_algo (),
*symkey_s2k, 1, 0, NULL, &canceled);
- if(!*symkey_dek || !(*symkey_dek)->keylen)
+ if (!*symkey_dek || !(*symkey_dek)->keylen)
{
xfree(*symkey_dek);
xfree(*symkey_s2k);
- return gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
+ return gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_INV_PASSPHRASE);
}
return 0;
@@ -619,15 +610,15 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
PKT_public_key *pk = pkr->pk;
unsigned int nbits = nbits_from_pk (pk);
- if (!gnupg_pk_is_compliant (opt.compliance,
- pk->pubkey_algo, pk->pkey, nbits, NULL))
+ if (!gnupg_pk_is_compliant (opt.compliance, pk->pubkey_algo, 0,
+ pk->pkey, nbits, NULL))
log_info (_("WARNING: key %s is not suitable for encryption"
" in %s mode\n"),
keystr_from_pk (pk),
gnupg_compliance_option_string (opt.compliance));
if (compliant
- && !gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
+ && !gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey,
nbits, NULL))
compliant = 0;
}
@@ -660,7 +651,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
make_session_key (cfx.dek);
if (DBG_CRYPTO)
- log_printhex ("DEK is: ", cfx.dek->key, cfx.dek->keylen );
+ log_printhex (cfx.dek->key, cfx.dek->keylen, "DEK is: ");
rc = write_pubkey_enc_from_list (ctrl, pk_list, cfx.dek, out);
if (rc)
@@ -854,7 +845,7 @@ encrypt_filter (void *opaque, int control,
make_session_key ( efx->cfx.dek );
if (DBG_CRYPTO)
- log_printhex ("DEK is: ", efx->cfx.dek->key, efx->cfx.dek->keylen);
+ log_printhex (efx->cfx.dek->key, efx->cfx.dek->keylen, "DEK is: ");
rc = write_pubkey_enc_from_list (efx->ctrl,
efx->pk_list, efx->cfx.dek, a);
diff --git a/g10/export.c b/g10/export.c
index 3f4b565..5149277 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -1028,11 +1028,11 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
/* log_debug ("XXX pubkey_algo=%d\n", pubkey_algo); */
/* log_debug ("XXX is_protected=%d\n", is_protected); */
/* log_debug ("XXX protect_algo=%d\n", protect_algo); */
- /* log_printhex ("XXX iv", iv, ivlen); */
+ /* log_printhex (iv, ivlen, "XXX iv"); */
/* log_debug ("XXX ivlen=%d\n", ivlen); */
/* log_debug ("XXX s2k_mode=%d\n", s2k_mode); */
/* log_debug ("XXX s2k_algo=%d\n", s2k_algo); */
- /* log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt); */
+ /* log_printhex (s2k_salt, sizeof s2k_salt, "XXX s2k_salt"); */
/* log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count); */
/* for (idx=0; skey[idx]; idx++) */
/* { */
@@ -1043,7 +1043,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
/* void *p; */
/* unsigned int nbits; */
/* p = gcry_mpi_get_opaque (skey[idx], &nbits); */
- /* log_printhex (NULL, p, (nbits+7)/8); */
+ /* log_printhex ( p, (nbits+7)/8, NULL); */
/* } */
/* else */
/* gcry_mpi_dump (skey[idx]); */
@@ -1110,7 +1110,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
/* void *p; */
/* unsigned int nbits; */
/* p = gcry_mpi_get_opaque (skey[idx], &nbits); */
- /* log_printhex (NULL, p, (nbits+7)/8); */
+ /* log_printhex (p, (nbits+7)/8, NULL); */
/* } */
/* else */
/* gcry_mpi_dump (skey[idx]); */
diff --git a/g10/getkey.c b/g10/getkey.c
index cafed3a..3d0dd0b 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -2414,8 +2414,8 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
{
PKT_user_id *uid = uidnode->pkt->pkt.user_id;
PKT_signature *sig = signode->pkt->pkt.signature;
- const byte *p, *sym, *hash, *zip;
- size_t n, nsym, nhash, nzip;
+ const byte *p, *sym, *aead, *hash, *zip;
+ size_t n, nsym, naead, nhash, nzip;
sig->flags.chosen_selfsig = 1;/* We chose this one. */
uid->created = 0; /* Not created == invalid. */
@@ -2470,6 +2470,9 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_SYM, &n);
sym = p;
nsym = p ? n : 0;
+ p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_AEAD, &n);
+ aead = p;
+ naead = p ? n : 0;
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_HASH, &n);
hash = p;
nhash = p ? n : 0;
@@ -2490,6 +2493,11 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
uid->prefs[n].type = PREFTYPE_SYM;
uid->prefs[n].value = *sym++;
}
+ for (; naead; naead--, n++)
+ {
+ uid->prefs[n].type = PREFTYPE_AEAD;
+ uid->prefs[n].value = *aead++;
+ }
for (; nhash; nhash--, n++)
{
uid->prefs[n].type = PREFTYPE_HASH;
@@ -2510,6 +2518,12 @@ fixup_uidnode (KBNODE uidnode, KBNODE signode, u32 keycreated)
if (p && n && (p[0] & 0x01))
uid->flags.mdc = 1;
+ /* See whether we have the AEAD feature. */
+ uid->flags.aead = 0;
+ p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n);
+ if (p && n && (p[0] & 0x02))
+ uid->flags.aead = 1;
+
/* And the keyserver modify flag. */
uid->flags.ks_modify = 1;
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS, &n);
@@ -3332,6 +3346,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
PKT_public_key *main_pk;
prefitem_t *prefs;
unsigned int mdc_feature;
+ unsigned int aead_feature;
if (keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
{
@@ -3393,7 +3408,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
* all preferences.
* Do a similar thing for the MDC feature flag. */
prefs = NULL;
- mdc_feature = 0;
+ mdc_feature = aead_feature = 0;
for (k = keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next)
{
if (k->pkt->pkttype == PKT_USER_ID
@@ -3402,6 +3417,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
{
prefs = k->pkt->pkt.user_id->prefs;
mdc_feature = k->pkt->pkt.user_id->flags.mdc;
+ aead_feature = k->pkt->pkt.user_id->flags.aead;
break;
}
}
@@ -3415,6 +3431,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
xfree (pk->prefs);
pk->prefs = copy_prefs (prefs);
pk->flags.mdc = mdc_feature;
+ pk->flags.aead = aead_feature;
}
}
}
diff --git a/g10/gpg.c b/g10/gpg.c
index 68cc220..1dc97a8 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -893,6 +893,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
ARGPARSE_s_n (oNoSymkeyCache, "no-symkey-cache", "@"),
ARGPARSE_s_n (oIncludeKeyBlock, "include-key-block", "@"),
+ ARGPARSE_s_n (oNoIncludeKeyBlock, "no-include-key-block", "@"),
ARGPARSE_s_n (oAutoKeyImport, "auto-key-import", "@"),
ARGPARSE_s_n (oNoAutoKeyImport, "no-auto-key-import", "@"),
@@ -4436,7 +4437,10 @@ main (int argc, char **argv)
case aDeleteSecretKeys:
case aDeleteSecretAndPublicKeys:
sl = NULL;
- /* I'm adding these in reverse order as add_to_strlist2
+ /* Print a note if the user did not specify any key. */
+ if (!argc && !opt.quiet)
+ log_info (_("Note: %s\n"), gpg_strerror (GPG_ERR_NO_KEY));
+ /* I'm adding these in reverse order as add_to_strlist2
reverses them again, and it's easier to understand in the
proper order :) */
for( ; argc; argc-- )
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 7ed997a..a7932ce 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -3069,6 +3069,23 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
}
tty_printf ("\n ");
+ tty_printf (_("AEAD: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_AEAD)
+ {
+ if (any)
+ tty_printf (", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (!openpgp_aead_test_algo (prefs[i].value)
+ && prefs[i].value < 100)
+ tty_printf ("%s", openpgp_aead_algo_name (prefs[i].value));
+ else
+ tty_printf ("[%d]", prefs[i].value);
+ }
+ }
+ tty_printf ("\n ");
tty_printf (_("Digest: "));
for (i = any = 0; prefs[i].type; i++)
{
@@ -3123,7 +3140,7 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
}
tty_printf ("%s", compress_algo_to_string (COMPRESS_ALGO_NONE));
}
- if (uid->flags.mdc || !uid->flags.ks_modify)
+ if (uid->flags.mdc || uid->flags.aead || !uid->flags.ks_modify)
{
tty_printf ("\n ");
tty_printf (_("Features: "));
@@ -3133,6 +3150,12 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
tty_printf ("MDC");
any = 1;
}
+ if (!uid->flags.aead)
+ {
+ if (any)
+ tty_printf (", ");
+ tty_printf ("AEAD");
+ }
if (!uid->flags.ks_modify)
{
if (any)
@@ -3171,12 +3194,15 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
for (i = 0; prefs[i].type; i++)
{
tty_printf (" %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
+ prefs[i].type == PREFTYPE_AEAD ? 'A' :
prefs[i].type == PREFTYPE_HASH ? 'H' :
prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?',
prefs[i].value);
}
if (uid->flags.mdc)
tty_printf (" [mdc]");
+ if (uid->flags.aead)
+ tty_printf (" [aead]");
if (!uid->flags.ks_modify)
tty_printf (" [no-ks-modify]");
tty_printf ("\n");
diff --git a/g10/keyid.c b/g10/keyid.c
index 5b868cd..69d85da 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -953,7 +953,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
else
{
if (DBG_PACKET)
- log_printhex ("keygrip=", array, 20);
+ log_printhex (array, 20, "keygrip=");
/* FIXME: Save the keygrip in PK. */
}
gcry_sexp_release (s_pkey);
diff --git a/g10/keylist.c b/g10/keylist.c
index 8ff4085..5b0f7ba 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -1340,7 +1340,7 @@ print_compliance_flags (PKT_public_key *pk,
es_fputs (gnupg_status_compliance_flag (CO_GNUPG), es_stdout);
any++;
}
- if (gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
+ if (gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey,
keylength, curvename))
{
es_fprintf (es_stdout, any ? " %s" : "%s",
diff --git a/g10/main.h b/g10/main.h
index 250467a..bb046ba 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -122,6 +122,12 @@ int openpgp_cipher_blocklen (cipher_algo_t algo);
int openpgp_cipher_test_algo(cipher_algo_t algo);
const char *openpgp_cipher_algo_name (cipher_algo_t algo);
+gpg_error_t openpgp_aead_test_algo (aead_algo_t algo);
+const char *openpgp_aead_algo_name (aead_algo_t algo);
+gpg_error_t openpgp_aead_algo_info (aead_algo_t algo,
+ enum gcry_cipher_modes *r_mode,
+ unsigned int *r_noncelen);
+
pubkey_algo_t map_pk_gcry_to_openpgp (enum gcry_pk_algos algo);
int openpgp_pk_test_algo (pubkey_algo_t algo);
int openpgp_pk_test_algo2 (pubkey_algo_t algo, unsigned int use);
@@ -223,7 +229,7 @@ int cpr_get_answer_okay_cancel (const char *keyword,
void display_online_help( const char *keyword );
/*-- encode.c --*/
-int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
+gpg_error_t setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
void encrypt_seskey (DEK *dek, DEK **seskey, byte *enckey);
int use_mdc (pk_list_t pk_list,int algo);
int encrypt_symmetric (const char *filename );
diff --git a/g10/mainproc.c b/g10/mainproc.c
index d278c2d..79ff211 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -97,6 +97,7 @@ struct mainproc_context
int trustletter; /* Temporary usage in list_node. */
ulong symkeys; /* Number of symmetrically encrypted session keys. */
struct kidlist_item *pkenc_list; /* List of encryption packets. */
+ int seen_pkt_encrypted_aead; /* PKT_ENCRYPTED_AEAD packet seen. */
struct {
unsigned int sig_seen:1; /* Set to true if a signature packet
has been seen. */
@@ -145,6 +146,7 @@ release_list( CTX c )
c->any.data = 0;
c->any.uncompress_failed = 0;
c->last_was_session_key = 0;
+ c->seen_pkt_encrypted_aead = 0;
xfree (c->dek);
c->dek = NULL;
}
@@ -252,47 +254,111 @@ add_signature (CTX c, PACKET *pkt)
return 1;
}
-static int
+
+static gpg_error_t
symkey_decrypt_seskey (DEK *dek, byte *seskey, size_t slen)
{
+ gpg_error_t err;
gcry_cipher_hd_t hd;
+ enum gcry_cipher_modes ciphermode;
+ unsigned int noncelen, keylen;
- if(slen < 17 || slen > 33)
+ if (dek->use_aead)
+ {
+ err = openpgp_aead_algo_info (dek->use_aead, &ciphermode, &noncelen);
+ if (err)
+ return err;
+ }
+ else
+ {
+ ciphermode = GCRY_CIPHER_MODE_CFB;
+ noncelen = 0;
+ }
+
+ /* Check that the session key has a size of 16 to 32 bytes. */
+ if ((dek->use_aead && (slen < (noncelen + 16 + 16)
+ || slen > (noncelen + 32 + 16)))
+ || (!dek->use_aead && (slen < 17 || slen > 33)))
{
log_error ( _("weird size for an encrypted session key (%d)\n"),
(int)slen);
- return GPG_ERR_BAD_KEY;
+ return gpg_error (GPG_ERR_BAD_KEY);
}
- if (openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1))
- BUG ();
- if (gcry_cipher_setkey ( hd, dek->key, dek->keylen ))
- BUG ();
- gcry_cipher_setiv ( hd, NULL, 0 );
- gcry_cipher_decrypt ( hd, seskey, slen, NULL, 0 );
- gcry_cipher_close ( hd );
-
- /* Here we can only test whether the algo given in decrypted
- * session key is a valid OpenPGP algo. With 11 defined
- * symmetric algorithms we will miss 4.3% of wrong passphrases
- * here. The actual checking is done later during bulk
- * decryption; we can't bring this check forward easily. */
- if (openpgp_cipher_test_algo (seskey[0]))
- return gpg_error (GPG_ERR_BAD_KEY);
-
- /* Now we replace the dek components with the real session key to
- decrypt the contents of the sequencing packet. */
+ err = openpgp_cipher_open (&hd, dek->algo, ciphermode, 1);
+ if (!err)
+ err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
+ if (!err)
+ err = gcry_cipher_setiv (hd, noncelen? seskey : NULL, noncelen);
+ if (err)
+ goto leave;
- dek->keylen=slen-1;
- dek->algo=seskey[0];
-
- if(dek->keylen > DIM(dek->key))
- BUG ();
+ if (dek->use_aead)
+ {
+ byte ad[4];
+
+ ad[0] = (0xc0 | PKT_SYMKEY_ENC);
+ ad[1] = 5;
+ ad[2] = dek->algo;
+ ad[3] = dek->use_aead;
+ err = gcry_cipher_authenticate (hd, ad, 4);
+ if (err)
+ goto leave;
+ gcry_cipher_final (hd);
+ keylen = slen - noncelen - 16;
+ err = gcry_cipher_decrypt (hd, seskey+noncelen, keylen, NULL, 0);
+ if (err)
+ goto leave;
+ err = gcry_cipher_checktag (hd, seskey+noncelen+keylen, 16);
+ if (err)
+ goto leave;
+ /* Now we replace the dek components with the real session key to
+ * decrypt the contents of the sequencing packet. */
+ if (keylen > DIM(dek->key))
+ {
+ err = gpg_error (GPG_ERR_TOO_LARGE);
+ goto leave;
+ }
+ dek->keylen = keylen;
+ memcpy (dek->key, seskey + noncelen, dek->keylen);
+ }
+ else
+ {
+ gcry_cipher_decrypt (hd, seskey, slen, NULL, 0);
+
+ /* Here we can only test whether the algo given in decrypted
+ * session key is a valid OpenPGP algo. With 11 defined
+ * symmetric algorithms we will miss 4.3% of wrong passphrases
+ * here. The actual checking is done later during bulk
+ * decryption; we can't bring this check forward easily. We
+ * need to use the GPG_ERR_CHECKSUM so that we won't run into
+ * the gnupg < 2.2 bug compatible case which would terminate the
+ * process on GPG_ERR_CIPHER_ALGO. Note that with AEAD (above)
+ * we will have a reliable test here. */
+ if (openpgp_cipher_test_algo (seskey[0])
+ || openpgp_cipher_get_algo_keylen (seskey[0]) != slen - 1)
+ {
+ err = gpg_error (GPG_ERR_CHECKSUM);
+ goto leave;
+ }
- memcpy(dek->key, seskey + 1, dek->keylen);
+ /* Now we replace the dek components with the real session key to
+ * decrypt the contents of the sequencing packet. */
+ keylen = slen-1;
+ if (keylen > DIM(dek->key))
+ {
+ err = gpg_error (GPG_ERR_TOO_LARGE);
+ goto leave;
+ }
+ dek->algo = seskey[0];
+ dek->keylen = slen-1;
+ memcpy (dek->key, seskey + 1, dek->keylen);
+ }
/*log_hexdump( "thekey", dek->key, dek->keylen );*/
+ leave:
+ gcry_cipher_close (hd);
return 0;
}
@@ -300,6 +366,7 @@ symkey_decrypt_seskey (DEK *dek, byte *seskey, size_t slen)
static void
proc_symkey_enc (CTX c, PACKET *pkt)
{
+ gpg_error_t err;
PKT_symkey_enc *enc;
enc = pkt->pkt.symkey_enc;
@@ -309,15 +376,20 @@ proc_symkey_enc (CTX c, PACKET *pkt)
{
int algo = enc->cipher_algo;
const char *s = openpgp_cipher_algo_name (algo);
+ const char *a = (enc->aead_algo ? openpgp_aead_algo_name (enc->aead_algo)
+ /**/ : "CFB");
if (!openpgp_cipher_test_algo (algo))
{
if (!opt.quiet)
{
+ /* Note: TMPSTR is only used to avoid i18n changes. */
+ char *tmpstr = xstrconcat (s, ".", a, NULL);
if (enc->seskeylen)
- log_info (_("%s encrypted session key\n"), s );
+ log_info (_("%s encrypted session key\n"), tmpstr);
else
- log_info (_("%s encrypted data\n"), s );
+ log_info (_("%s encrypted data\n"), tmpstr);
+ xfree (tmpstr);
}
}
else
@@ -349,6 +421,7 @@ proc_symkey_enc (CTX c, PACKET *pkt)
if (c->dek)
{
c->dek->symmetric = 1;
+ c->dek->use_aead = enc->aead_algo;
/* FIXME: This doesn't work perfectly if a symmetric key
comes before a public key in the message - if the
@@ -359,9 +432,16 @@ proc_symkey_enc (CTX c, PACKET *pkt)
come later. */
if (enc->seskeylen)
{
- if (symkey_decrypt_seskey (c->dek,
- enc->seskey, enc->seskeylen))
+ err = symkey_decrypt_seskey (c->dek,
+ enc->seskey, enc->seskeylen);
+ if (err)
{
+ log_info ("decryption of the symmetrically encrypted"
+ " session key failed: %s\n",
+ gpg_strerror (err));
+ if (gpg_err_code (err) != GPG_ERR_BAD_KEY
+ && gpg_err_code (err) != GPG_ERR_CHECKSUM)
+ log_fatal ("process terminated to be bug compatible\n");
if (c->dek->s2k_cacheid[0])
{
if (opt.debug)
@@ -550,6 +630,9 @@ proc_encrypted (CTX c, PACKET *pkt)
int result = 0;
int early_plaintext = literals_seen;
+ if (pkt->pkttype == PKT_ENCRYPTED_AEAD)
+ c->seen_pkt_encrypted_aead = 1;
+
if (early_plaintext)
{
log_info (_("WARNING: multiple plaintexts seen\n"));
@@ -656,8 +739,8 @@ proc_encrypted (CTX c, PACKET *pkt)
memset (pk, 0, sizeof *pk);
pk->pubkey_algo = i->pubkey_algo;
if (get_pubkey (c->ctrl, pk, i->kid) != 0
- || ! gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
- nbits_from_pk (pk), NULL))
+ || ! gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0,
+ pk->pkey, nbits_from_pk (pk), NULL))
compliant = 0;
release_public_key_parts (pk);
}
@@ -683,7 +766,8 @@ proc_encrypted (CTX c, PACKET *pkt)
;
else if (!result
&& !opt.ignore_mdc_error
- && !pkt->pkt.encrypted->mdc_method)
+ && !pkt->pkt.encrypted->mdc_method
+ && !pkt->pkt.encrypted->aead_algo)
{
/* The message has been decrypted but does not carry an MDC.
* The option --ignore-mdc-error has also not been used. To
@@ -712,17 +796,25 @@ proc_encrypted (CTX c, PACKET *pkt)
write_status (STATUS_DECRYPTION_FAILED);
}
else if (!result || (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE
+ && !pkt->pkt.encrypted->aead_algo
&& opt.ignore_mdc_error))
{
+ /* All is fine or for an MDC message the MDC failed but the
+ * --ignore-mdc-error option is active. For compatibility
+ * reasons we issue GOODMDC also for AEAD messages. */
write_status (STATUS_DECRYPTION_OKAY);
if (opt.verbose > 1)
log_info(_("decryption okay\n"));
- if (pkt->pkt.encrypted->mdc_method && !result)
+
+ if (pkt->pkt.encrypted->aead_algo)
+ write_status (STATUS_GOODMDC);
+ else if (pkt->pkt.encrypted->mdc_method && !result)
write_status (STATUS_GOODMDC);
else
log_info (_("WARNING: message was not integrity protected\n"));
}
- else if (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE)
+ else if (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE
+ || gpg_err_code (result) == GPG_ERR_TRUNCATED)
{
glo_ctrl.lasterr = result;
log_error (_("WARNING: encrypted message has been manipulated!\n"));
@@ -732,6 +824,7 @@ proc_encrypted (CTX c, PACKET *pkt)
else
{
if ((gpg_err_code (result) == GPG_ERR_BAD_KEY
+ || gpg_err_code (result) == GPG_ERR_CHECKSUM
|| gpg_err_code (result) == GPG_ERR_CIPHER_ALGO)
&& *c->dek->s2k_cacheid != '\0')
{
@@ -761,6 +854,21 @@ proc_encrypted (CTX c, PACKET *pkt)
}
+static int
+have_seen_pkt_encrypted_aead( CTX c )
+{
+ CTX cc;
+
+ for (cc = c; cc; cc = cc->anchor)
+ {
+ if (cc->seen_pkt_encrypted_aead)
+ return 1;
+ }
+
+ return 0;
+}
+
+
static void
proc_plaintext( CTX c, PACKET *pkt )
{
@@ -836,7 +944,7 @@ proc_plaintext( CTX c, PACKET *pkt )
}
}
- if (!any && !opt.skip_verify)
+ if (!any && !opt.skip_verify && !have_seen_pkt_encrypted_aead(c))
{
/* This is for the old GPG LITERAL+SIG case. It's not legal
according to 2440, so hopefully it won't come up that often.
@@ -1467,7 +1575,8 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
case PKT_ENCRYPTED:
- case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break;
+ case PKT_ENCRYPTED_MDC:
+ case PKT_ENCRYPTED_AEAD:proc_encrypted (c, pkt); break;
case PKT_COMPRESSED: rc = proc_compressed (c, pkt); break;
default: newpkt = 0; break;
}
@@ -1483,6 +1592,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
case PKT_PUBKEY_ENC:
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
+ case PKT_ENCRYPTED_AEAD:
write_status_text( STATUS_UNEXPECTED, "0" );
rc = GPG_ERR_UNEXPECTED;
goto leave;
@@ -1510,7 +1620,8 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
case PKT_ENCRYPTED:
- case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break;
+ case PKT_ENCRYPTED_MDC:
+ case PKT_ENCRYPTED_AEAD: proc_encrypted (c, pkt); break;
case PKT_PLAINTEXT: proc_plaintext (c, pkt); break;
case PKT_COMPRESSED: rc = proc_compressed (c, pkt); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig (c, pkt); break;
@@ -1537,7 +1648,8 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
case PKT_ENCRYPTED:
- case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break;
+ case PKT_ENCRYPTED_MDC:
+ case PKT_ENCRYPTED_AEAD: proc_encrypted (c, pkt); break;
case PKT_PLAINTEXT: proc_plaintext (c, pkt); break;
case PKT_COMPRESSED: rc = proc_compressed (c, pkt); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig (c, pkt); break;
@@ -2317,7 +2429,7 @@ check_sig_and_print (CTX c, kbnode_t node)
/* Print compliance warning for Good signatures. */
if (!rc && pk && !opt.quiet
- && !gnupg_pk_is_compliant (opt.compliance, pk->pubkey_algo,
+ && !gnupg_pk_is_compliant (opt.compliance, pk->pubkey_algo, 0,
pk->pkey, nbits_from_pk (pk), NULL))
{
log_info (_("WARNING: This key is not suitable for signing"
@@ -2401,7 +2513,7 @@ check_sig_and_print (CTX c, kbnode_t node)
/* Compute compliance with CO_DE_VS. */
if (pk && is_status_enabled ()
- && gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
+ && gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey,
nbits_from_pk (pk), NULL)
&& gnupg_digest_is_compliant (CO_DE_VS, sig->digest_algo))
write_status_strings (STATUS_VERIFICATION_COMPLIANCE_MODE,
diff --git a/g10/misc.c b/g10/misc.c
index 291d36f..22ed47e 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -70,6 +70,10 @@
#include "../common/i18n.h"
#include "../common/zb32.h"
+/* FIXME: Libgcrypt 1.9 will support EAX. Until we name this a
+ * requirement we hardwire the enum used for EAX. */
+#define MY_GCRY_CIPHER_MODE_EAX 14
+
#ifdef ENABLE_SELINUX_HACKS
/* A object and a global variable to keep track of files marked as
@@ -602,6 +606,80 @@ openpgp_cipher_algo_name (cipher_algo_t algo)
}
+/* Return 0 if ALGO is supported. Return an error if not. */
+gpg_error_t
+openpgp_aead_test_algo (aead_algo_t algo)
+{
+ /* FIXME: We currently have no easy way to test whether libgcrypt
+ * implements a mode. The only way we can do this is to open a
+ * cipher context with that mode and close it immediately. That is
+ * a bit costly. So we look at the libgcrypt version and assume
+ * nothing has been patched out. */
+ switch (algo)
+ {
+ case AEAD_ALGO_NONE:
+ break;
+
+ case AEAD_ALGO_EAX:
+#if GCRYPT_VERSION_NUMBER < 0x010900
+ break;
+#else
+ return 0;
+#endif
+
+ case AEAD_ALGO_OCB:
+ return 0;
+ }
+
+ return gpg_error (GPG_ERR_INV_CIPHER_MODE);
+}
+
+
+/* Map the OpenPGP AEAD algorithm with ID ALGO to a string
+ * representation of the algorithm name. For unknown algorithm IDs
+ * this function returns "?". */
+const char *
+openpgp_aead_algo_name (aead_algo_t algo)
+{
+ switch (algo)
+ {
+ case AEAD_ALGO_NONE: break;
+ case AEAD_ALGO_EAX: return "EAX";
+ case AEAD_ALGO_OCB: return "OCB";
+ }
+
+ return "?";
+}
+
+
+/* Return information for the AEAD algorithm ALGO. The corresponding
+ * Libgcrypt ciphermode is stored at R_MODE and the required number of
+ * octets for the nonce at R_NONCELEN. On error and error code is
+ * returned. Note that the taglen is always 128 bits. */
+gpg_error_t
+openpgp_aead_algo_info (aead_algo_t algo, enum gcry_cipher_modes *r_mode,
+ unsigned int *r_noncelen)
+{
+ switch (algo)
+ {
+ case AEAD_ALGO_OCB:
+ *r_mode = GCRY_CIPHER_MODE_OCB;
+ *r_noncelen = 15;
+ break;
+
+ case AEAD_ALGO_EAX:
+ *r_mode = MY_GCRY_CIPHER_MODE_EAX;
+ *r_noncelen = 16;
+ break;
+
+ default:
+ log_error ("unsupported AEAD algo %d\n", algo);
+ return gpg_error (GPG_ERR_INV_CIPHER_MODE);
+ }
+ return 0;
+}
+
+
/* Return 0 if ALGO is a supported OpenPGP public key algorithm. */
int
openpgp_pk_test_algo (pubkey_algo_t algo)
diff --git a/g10/packet.h b/g10/packet.h
index 4c0655c..187fffc 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -77,7 +77,8 @@ typedef enum {
PREFTYPE_NONE = 0,
PREFTYPE_SYM = 1,
PREFTYPE_HASH = 2,
- PREFTYPE_ZIP = 3
+ PREFTYPE_ZIP = 3,
+ PREFTYPE_AEAD = 4
} preftype_t;
typedef struct {
@@ -104,6 +105,8 @@ typedef struct {
be different from the algorithm that is used to encrypt the SED
packet.) */
byte cipher_algo;
+ /* The AEAD algorithm or 0 for CFB encryption. */
+ byte aead_algo;
/* The string-to-key specifier. */
STRING2KEY s2k;
/* The length of SESKEY in bytes or 0 if this packet does not
@@ -111,7 +114,8 @@ typedef struct {
S2K function on the password is the session key. See RFC 4880,
Section 5.3.) */
byte seskeylen;
- /* The session key as encrypted by the S2K specifier. */
+ /* The session key as encrypted by the S2K specifier. For AEAD this
+ * includes the nonce and the authentication tag. */
byte seskey[1];
} PKT_symkey_enc;
@@ -297,6 +301,7 @@ typedef struct
struct
{
unsigned int mdc:1;
+ unsigned int aead:1;
unsigned int ks_modify:1;
unsigned int compacted:1;
unsigned int primary:2; /* 2 if set via the primary flag, 1 if calculated */
@@ -393,6 +398,7 @@ typedef struct
struct
{
unsigned int mdc:1; /* MDC feature set. */
+ unsigned int aead:1; /* AEAD feature set. */
unsigned int disabled_valid:1;/* The next flag is valid. */
unsigned int disabled:1; /* The key has been disabled. */
unsigned int primary:1; /* This is a primary key. */
@@ -463,12 +469,13 @@ typedef struct {
typedef struct {
/* Remaining length of encrypted data. */
u32 len;
- /* When encrypting, the first block size bytes of data are random
- data and the following 2 bytes are copies of the last two bytes
- of the random data (RFC 4880, Section 5.7). This provides a
- simple check that the key is correct. extralen is the size of
- this extra data. This is used by build_packet when writing out
- the packet's header. */
+ /* When encrypting in CFB mode, the first block size bytes of data
+ * are random data and the following 2 bytes are copies of the last
+ * two bytes of the random data (RFC 4880, Section 5.7). This
+ * provides a simple check that the key is correct. EXTRALEN is the
+ * size of this extra data or, in AEAD mode, the length of the
+ * headers and the tags. This is used by build_packet when writing
+ * out the packet's header. */
int extralen;
/* Whether the serialized version of the packet used / should use
the new format. */
@@ -480,6 +487,15 @@ typedef struct {
/* If 0, MDC is disabled. Otherwise, the MDC method that was used
(currently, only DIGEST_ALGO_SHA1 is supported). */
byte mdc_method;
+ /* If 0, AEAD is not used. Otherwise, the used AEAD algorithm.
+ * MDC_METHOD (above) shall be zero if AEAD is used. */
+ byte aead_algo;
+ /* The cipher algo for/from the AEAD packet. 0 for other encryption
+ * packets. */
+ byte cipher_algo;
+ /* The chunk byte from the AEAD packet. */
+ byte chunkbyte;
+
/* An iobuf holding the data to be decrypted. (This is not used for
encryption!) */
iobuf_t buf;
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 6646bec..9cb254e 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -81,6 +81,9 @@ static int parse_compressed (IOBUF inp, int pkttype, unsigned long pktlen,
PACKET * packet, int new_ctb);
static int parse_encrypted (IOBUF inp, int pkttype, unsigned long pktlen,
PACKET * packet, int new_ctb, int partial);
+static gpg_error_t parse_encrypted_aead (IOBUF inp, int pkttype,
+ unsigned long pktlen, PACKET *packet,
+ int partial);
static int parse_mdc (IOBUF inp, int pkttype, unsigned long pktlen,
PACKET * packet, int new_ctb);
static int parse_gpg_control (IOBUF inp, int pkttype, unsigned long pktlen,
@@ -665,6 +668,7 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
case PKT_PLAINTEXT:
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
+ case PKT_ENCRYPTED_AEAD:
case PKT_COMPRESSED:
iobuf_set_partial_body_length_mode (inp, c & 0xff);
pktlen = 0; /* To indicate partial length. */
@@ -852,6 +856,9 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
case PKT_MDC:
rc = parse_mdc (inp, pkttype, pktlen, pkt, new_ctb);
break;
+ case PKT_ENCRYPTED_AEAD:
+ rc = parse_encrypted_aead (inp, pkttype, pktlen, pkt, partial);
+ break;
case PKT_GPG_CONTROL:
rc = parse_gpg_control (inp, pkttype, pktlen, pkt, partial);
break;
@@ -1127,19 +1134,17 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
{
PKT_symkey_enc *k;
int rc = 0;
- int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen;
+ int i, version, s2kmode, cipher_algo, aead_algo, hash_algo, seskeylen, minlen;
if (pktlen < 4)
- {
- log_error ("packet(%d) too short\n", pkttype);
- if (list_mode)
- es_fprintf (listfp, ":symkey enc packet: [too short]\n");
- rc = gpg_error (GPG_ERR_INV_PACKET);
- goto leave;
- }
+ goto too_short;
version = iobuf_get_noeof (inp);
pktlen--;
- if (version != 4)
+ if (version == 4)
+ ;
+ else if (version == 5)
+ ;
+ else
{
log_error ("packet(%d) with unknown version %d\n", pkttype, version);
if (list_mode)
@@ -1157,6 +1162,15 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
}
cipher_algo = iobuf_get_noeof (inp);
pktlen--;
+ if (version == 5)
+ {
+ aead_algo = iobuf_get_noeof (inp);
+ pktlen--;
+ }
+ else
+ aead_algo = 0;
+ if (pktlen < 2)
+ goto too_short;
s2kmode = iobuf_get_noeof (inp);
pktlen--;
hash_algo = iobuf_get_noeof (inp);
@@ -1191,6 +1205,7 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
+ seskeylen - 1);
k->version = version;
k->cipher_algo = cipher_algo;
+ k->aead_algo = aead_algo;
k->s2k.mode = s2kmode;
k->s2k.hash_algo = hash_algo;
if (s2kmode == 1 || s2kmode == 3)
@@ -1221,10 +1236,20 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
if (list_mode)
{
es_fprintf (listfp,
- ":symkey enc packet: version %d, cipher %d, s2k %d, hash %d",
- version, cipher_algo, s2kmode, hash_algo);
+ ":symkey enc packet: version %d, cipher %d, aead %d,"
+ "s2k %d, hash %d",
+ version, cipher_algo, aead_algo, s2kmode, hash_algo);
if (seskeylen)
- es_fprintf (listfp, ", seskey %d bits", (seskeylen - 1) * 8);
+ {
+ /* To compute the size of the session key we need to know
+ * the size of the AEAD nonce which we may not know. Thus
+ * we show only the size of the entire encrypted session
+ * key. */
+ if (aead_algo)
+ es_fprintf (listfp, ", encrypted seskey %d bytes", seskeylen);
+ else
+ es_fprintf (listfp, ", seskey %d bits", (seskeylen - 1) * 8);
+ }
es_fprintf (listfp, "\n");
if (s2kmode == 1 || s2kmode == 3)
{
@@ -1241,6 +1266,13 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
leave:
iobuf_skip_rest (inp, pktlen, 0);
return rc;
+
+ too_short:
+ log_error ("packet(%d) too short\n", pkttype);
+ if (list_mode)
+ es_fprintf (listfp, ":symkey enc packet: [too short]\n");
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
}
@@ -1421,6 +1453,11 @@ dump_sig_subpkt (int hashed, int type, int critical,
for (i = 0; i < length; i++)
es_fprintf (listfp, " %d", buffer[i]);
break;
+ case SIGSUBPKT_PREF_AEAD:
+ es_fputs ("pref-aead-algos:", listfp);
+ for (i = 0; i < length; i++)
+ es_fprintf (listfp, " %d", buffer[i]);
+ break;
case SIGSUBPKT_REV_KEY:
es_fputs ("revocation key: ", listfp);
if (length < 22)
@@ -1601,6 +1638,7 @@ parse_one_sig_subpkt (const byte * buffer, size_t n, int type)
case SIGSUBPKT_KEY_FLAGS:
case SIGSUBPKT_KS_FLAGS:
case SIGSUBPKT_PREF_SYM:
+ case SIGSUBPKT_PREF_AEAD:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
case SIGSUBPKT_POLICY:
@@ -3253,6 +3291,9 @@ parse_encrypted (IOBUF inp, int pkttype, unsigned long pktlen,
ed->buf = NULL;
ed->new_ctb = new_ctb;
ed->is_partial = partial;
+ ed->aead_algo = 0;
+ ed->cipher_algo = 0; /* Only used with AEAD. */
+ ed->chunkbyte = 0; /* Only used with AEAD. */
if (pkttype == PKT_ENCRYPTED_MDC)
{
/* Fixme: add some pktlen sanity checks. */
@@ -3344,6 +3385,81 @@ parse_mdc (IOBUF inp, int pkttype, unsigned long pktlen,
}
+static gpg_error_t
+parse_encrypted_aead (iobuf_t inp, int pkttype, unsigned long pktlen,
+ PACKET *pkt, int partial)
+{
+ int rc = 0;
+ PKT_encrypted *ed;
+ unsigned long orig_pktlen = pktlen;
+ int version;
+
+ ed = pkt->pkt.encrypted = xtrymalloc (sizeof *pkt->pkt.encrypted);
+ if (!ed)
+ return gpg_error_from_syserror ();
+ ed->len = 0;
+ ed->extralen = 0; /* (only used in build_packet.) */
+ ed->buf = NULL;
+ ed->new_ctb = 1; /* (packet number requires a new CTB anyway.) */
+ ed->is_partial = partial;
+ ed->mdc_method = 0;
+ /* A basic sanity check. We need one version byte, one algo byte,
+ * one aead algo byte, one chunkbyte, at least 15 byte IV. */
+ if (orig_pktlen && pktlen < 19)
+ {
+ log_error ("packet(%d) too short\n", pkttype);
+ if (list_mode)
+ es_fputs (":aead encrypted packet: [too short]\n", listfp);
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ iobuf_skip_rest (inp, pktlen, partial);
+ goto leave;
+ }
+
+ version = iobuf_get_noeof (inp);
+ if (orig_pktlen)
+ pktlen--;
+ if (version != 1)
+ {
+ log_error ("aead encrypted packet with unknown version %d\n",
+ version);
+ if (list_mode)
+ es_fputs (":aead encrypted packet: [unknown version]\n", listfp);
+ /*skip_rest(inp, pktlen); should we really do this? */
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
+ }
+
+ ed->cipher_algo = iobuf_get_noeof (inp);
+ if (orig_pktlen)
+ pktlen--;
+ ed->aead_algo = iobuf_get_noeof (inp);
+ if (orig_pktlen)
+ pktlen--;
+ ed->chunkbyte = iobuf_get_noeof (inp);
+ if (orig_pktlen)
+ pktlen--;
+
+ /* Store the remaining length of the encrypted data. We read the
+ * rest during decryption. */
+ ed->len = pktlen;
+
+ if (list_mode)
+ {
+ es_fprintf (listfp, ":aead encrypted packet: cipher=%u aead=%u cb=%u\n",
+ ed->cipher_algo, ed->aead_algo, ed->chunkbyte);
+ if (orig_pktlen)
+ es_fprintf (listfp, "\tlength: %lu\n", orig_pktlen);
+ else
+ es_fprintf (listfp, "\tlength: unknown\n");
+ }
+
+ ed->buf = inp;
+
+ leave:
+ return rc;
+}
+
+
/*
* This packet is internally generated by us (in armor.c) to transfer
* some information to the lower layer. To make sure that this packet
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 10574ec..df80af8 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -212,6 +212,10 @@ read_passphrase_from_fd( int fd )
* Ask the GPG Agent for the passphrase.
* If NOCACHE is set the symmetric passpharse caching will not be used.
*
+ * If REPEAT is positive, a new passphrase is requested and the agent
+ * shall require REPEAT times repetitions of the entered passphrase.
+ * This is used for symmetric encryption.
+ *
* Note that TRYAGAIN_TEXT must not be translated. If CANCELED is not
* NULL, the function does set it to 1 if the user canceled the
* operation. If CACHEID is not NULL, it will be used as the cacheID
@@ -219,7 +223,7 @@ read_passphrase_from_fd( int fd )
* computed, this will be used as the cacheid.
*/
static char *
-passphrase_get (int nocache, const char *cacheid, int repeat,
+passphrase_get (int newsymkey, int nocache, const char *cacheid, int repeat,
const char *tryagain_text, int *canceled)
{
int rc;
@@ -240,9 +244,19 @@ passphrase_get (int nocache, const char *cacheid, int repeat,
if (tryagain_text)
tryagain_text = _(tryagain_text);
+ /* Here we have:
+ * REPEAT is set in create mode and if opt.passphrase_repeat is set.
+ * (Thus it is not a clean indication that we want a new passphrase).
+ * NOCACHE is set in create mode or if --no-symkey-cache is used.
+ * CACHEID is only set if caching shall be used.
+ * NEWSYMKEY has been added latter to make it clear that a new key
+ * is requested. The whole chain of API is a bit too complex since
+ * we we stripped things out over time; however, there is no time
+ * for a full state analysis and thus this new parameter.
+ */
rc = agent_get_passphrase (my_cacheid, tryagain_text, NULL,
_("Enter passphrase\n"),
- repeat, nocache, &pw);
+ newsymkey, repeat, nocache, &pw);
i18n_switchback (orig_codeset);
@@ -318,7 +332,7 @@ passphrase_to_dek (int cipher_algo, STRING2KEY *s2k,
*canceled = 0;
if (opt.no_symkey_cache)
- nocache = 1; /* Force no symmtric key caching. */
+ nocache = 1; /* Force no symmetric key caching. */
if ( !s2k )
{
@@ -389,7 +403,7 @@ passphrase_to_dek (int cipher_algo, STRING2KEY *s2k,
}
/* Divert to the gpg-agent. */
- pw = passphrase_get (create && nocache, s2k_cacheid,
+ pw = passphrase_get (create, create && nocache, s2k_cacheid,
create? opt.passphrase_repeat : 0,
tryagain_text, canceled);
if (*canceled)
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 4e6f893..30a4bc0 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -92,7 +92,7 @@ get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
{
/* Check compliance. */
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
- sk->pubkey_algo,
+ sk->pubkey_algo, 0,
sk->pkey, nbits_from_pk (sk), NULL))
{
log_info (_("key %s is not suitable for decryption"
@@ -133,7 +133,7 @@ get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
/* Check compliance. */
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
- sk->pubkey_algo,
+ sk->pubkey_algo, 0,
sk->pkey, nbits_from_pk (sk), NULL))
{
log_info (_("key %s is not suitable for decryption"
@@ -259,7 +259,7 @@ get_it (ctrl_t ctrl,
* CSUM
*/
if (DBG_CRYPTO)
- log_printhex ("DEK frame:", frame, nframe);
+ log_printhex (frame, nframe, "DEK frame:");
n = 0;
if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
@@ -288,10 +288,7 @@ get_it (ctrl_t ctrl,
goto leave;
/* Now the frame are the bytes decrypted but padded session key. */
-
- /* Allow double padding for the benefit of DEK size concealment.
- Higher than this is wasteful. */
- if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8
+ if (!nframe || nframe <= 8
|| frame[nframe-1] > nframe)
{
err = gpg_error (GPG_ERR_WRONG_SECKEY);
@@ -375,7 +372,7 @@ get_it (ctrl_t ctrl,
if (DBG_CLOCK)
log_clock ("decryption ready");
if (DBG_CRYPTO)
- log_printhex ("DEK is:", dek->key, dek->keylen);
+ log_printhex (dek->key, dek->keylen, "DEK is:");
/* Check that the algo is in the preferences and whether it has
* expired. Also print a status line with the key's fingerprint. */
diff --git a/g10/sig-check.c b/g10/sig-check.c
index 44e7871..e71e662 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -164,7 +164,7 @@ check_signature2 (ctrl_t ctrl,
else if (get_pubkey_for_sig (ctrl, pk, sig, forced_pk))
rc = gpg_error (GPG_ERR_NO_PUBKEY);
else if (!gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
- pk->pubkey_algo, pk->pkey,
+ pk->pubkey_algo, 0, pk->pkey,
nbits_from_pk (pk),
NULL))
{
diff --git a/g10/sign.c b/g10/sign.c
index 6e9f68e..a71ceda 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -395,7 +395,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, pksk->pubkey_algo,
+ if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING,
+ pksk->pubkey_algo, 0,
pksk->pkey, nbits_from_pk (pksk), NULL))
{
log_error (_("key %s may not be used for signing in %s mode\n"),
diff --git a/g13/call-syshelp.c b/g13/call-syshelp.c
index 8a50c3f..b160ba3 100644
--- a/g13/call-syshelp.c
+++ b/g13/call-syshelp.c
@@ -366,7 +366,7 @@ create_inq_cb (void *opaque, const char *line)
void *ciphertext;
size_t ciphertextlen;
- log_printhex ("plain", plaintext, plaintextlen);
+ log_printhex (plaintext, plaintextlen, "plain");
err = g13_encrypt_keyblob (parm->ctrl,
plaintext, plaintextlen,
&ciphertext, &ciphertextlen);
diff --git a/g13/g13tuple.c b/g13/g13tuple.c
index b10ebbc..6693826 100644
--- a/g13/g13tuple.c
+++ b/g13/g13tuple.c
@@ -318,7 +318,7 @@ dump_tupledesc (tupledesc_t tuples)
if (n < 100 && all_printable (value, n))
log_printf ("%.*s\n", (int)n, (const char*)value);
else
- log_printhex ("", value, n);
+ log_printhex (value, n, "");
break;
case KEYBLOB_TAG_CONT_NSEC:
@@ -327,11 +327,11 @@ dump_tupledesc (tupledesc_t tuples)
if (!convert_uint (value, n, &uint))
log_printf ("%llu\n", uint);
else
- log_printhex ("", value, n);
+ log_printhex (value, n, "");
break;
default:
- log_printhex ("", value, n);
+ log_printhex (value, n, "");
break;
}
}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 15f7485..bd90a6c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -79,6 +79,7 @@ g10/verify.c
kbx/kbxutil.c
+scd/app-p15.c
scd/app-nks.c
scd/app-openpgp.c
scd/app-dinsig.c
diff --git a/po/ca.po b/po/ca.po
index a52d77a..1927a17 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -115,6 +115,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3811,6 +3814,9 @@ msgstr "error: l'empremta digital és invàlida\n"
msgid "subkey \"%s\" not found\n"
msgstr "no s'ha trobat la clau «%s»: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Resum: "
@@ -6607,6 +6613,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Forma d'ús: gpg [opcions] [fitxers] (-h per a veure l'ajuda)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "canvia la contrasenya"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6628,10 +6654,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "canvia la contrasenya"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "canvia la contrasenya"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Seleccioneu la raó de la revocació:\n"
@@ -6642,9 +6664,6 @@ msgstr "Seleccioneu la raó de la revocació:\n"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6700,16 +6719,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6967,6 +6976,10 @@ msgstr "s'està escrivint la clau secreta a «%s»\n"
msgid "certificate policy not allowed"
msgstr "s'està escrivint la clau secreta a «%s»\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "no s'ha pogut emmagatzemar l'empremta digital: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6975,6 +6988,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: no s'ha pogut accedir: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7603,10 +7621,6 @@ msgstr "error en la creació de la contrasenya: %s\n"
msgid "error reading input: %s\n"
msgstr "error en la lectura de «%s»: %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "no s'ha pogut emmagatzemar l'empremta digital: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7686,8 +7700,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "error en la creació de la contrasenya: %s\n"
+msgid "algorithm:"
+msgstr "armadura: %s\n"
#, c-format
msgid ""
@@ -8019,15 +8033,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "error en crear «%s»: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "l'algoritme de dispersió és invàlid «%s»\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "la resposta de l'agent és invàlida\n"
@@ -8038,6 +8043,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "no s'han pogut canviar els permissos de «%s»: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "l'algoritme de dispersió és invàlid «%s»\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
#| msgid "changing permission of `%s' failed: %s\n"
msgid "creating S-expression failed: %s\n"
msgstr "no s'han pogut canviar els permissos de «%s»: %s\n"
@@ -8834,11 +8848,6 @@ msgstr "Certificat correcte"
msgid "failed to allocate OCSP context: %s\n"
msgstr "no s'ha pogut inicialitzar la base de dades de confiança: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: no s'ha pogut accedir: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9433,6 +9442,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "error en la creació de la contrasenya: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/cs.po b/po/cs.po
index 3a2f82b..2dd0cd4 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -125,6 +125,9 @@ msgstr "neshodují se – zkuste to znovu"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (pokus %d z %d)"
@@ -3510,6 +3513,9 @@ msgstr "„%s“ není řádný otisk\n"
msgid "subkey \"%s\" not found\n"
msgstr "podklÃ­Ä â€ž%s“ nenalezen\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Hash: "
@@ -6214,6 +6220,26 @@ msgstr ""
"Syntaxe: kbxutil [volby] [soubory]\n"
"Vypisuje, exportuje, importuje schránku na klíÄe (keybox).\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr "%sČíslo: %s%%0ADržitel: %s%s"
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr "Zbývá pokusů: %d"
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+"||Prosím, zadejte PIN klíÄe urÄeného na tvorbu kvalifikovaných podpisů."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Prosím, zadejte PIN pro standardní klíÄe."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "schází RSA modulus nebo nemá velikost %d bitů\n"
@@ -6235,9 +6261,6 @@ msgstr "NullPIN ještě nebyl změněn\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Prosím, zadejte nový PIN pro standardní klíÄe."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Prosím, zadejte PIN pro standardní klíÄe."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "|NP|Prosím, zadejte nový kód pro odblokování (PUK) standardních klíÄů."
@@ -6248,10 +6271,6 @@ msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
"|N|Prosím, zadejte nový PIN klíÄe urÄeného na tvorbu kvalifikovaných podpisů."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-"||Prosím, zadejte PIN klíÄe urÄeného na tvorbu kvalifikovaných podpisů."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6310,16 +6329,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr "%sČíslo: %s%%0ADržitel: %s%%0APoÄítadlo: %lu%s"
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr "%sČíslo: %s%%0ADržitel: %s%s"
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr "Zbývá pokusů: %d"
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "použije se výchozí PIN jako %s\n"
@@ -6570,6 +6579,10 @@ msgid "certificate policy not allowed"
msgstr "certifikaÄní politika není dovolena"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "otisk se nepodařilo získat\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "hledám vydavatele na jiném místě\n"
@@ -6578,6 +6591,10 @@ msgid "number of issuers matching: %d\n"
msgstr "poÄet odpovídajících vydavatelů: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "authorityInfoAccess nelze získat: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "hledám vydavatele ve vyrovnávací paměti Dirmngr\n"
@@ -7162,10 +7179,6 @@ msgid "error reading input: %s\n"
msgstr "chyba pÅ™i Ätení vstupu: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "otisk se nepodařilo získat\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "problém při hledání existujícího certifikátu: %s\n"
@@ -7255,9 +7268,10 @@ msgstr "Podpis vytvořen "
msgid "[date not given]"
msgstr "[datum neudáno]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " pomocí certifikátu s ID 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "algoritmus: %s"
#, c-format
msgid ""
@@ -7594,14 +7608,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "chyba při získávání dat ze souboru keše: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "neznámý hašovací algoritmus „%s“\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "gcry_md_open selhalo na algoritmu %d: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "z libksba obdržen neplatný S-výraz\n"
@@ -7610,6 +7616,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "převod S-výrazu se nezdařil: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "neznámý hašovací algoritmus „%s“\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "gcry_md_open selhalo na algoritmu %d: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "výroba S-výrazu selhala: %s\n"
@@ -8363,10 +8377,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "alokace OCSP kontextu selhala: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "authorityInfoAccess nelze získat: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "žádný výchozí OCSP odpovídaÄ nedefinován\n"
@@ -8939,6 +8949,9 @@ msgstr ""
"Syntaxe: gpg-check-pattern [volby] soubor_se_vzorem\n"
"Prověří heslo zadané na vstupu proti souboru se vzory\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " pomocí certifikátu s ID 0x%08lX\n"
+
#, fuzzy
#~| msgid "option '%s' may not be used in %s mode\n"
#~ msgid ""
diff --git a/po/da.po b/po/da.po
index ec9c191..4c1dd54 100644
--- a/po/da.po
+++ b/po/da.po
@@ -116,6 +116,9 @@ msgstr "matcher ikke - prøv igen"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (forsøg %d af %d)"
@@ -3767,6 +3770,9 @@ msgstr "ugyldig fingeraftryk"
msgid "subkey \"%s\" not found\n"
msgstr "nøglen »%s« blev ikke fundet: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Sammendrag: "
@@ -6555,6 +6561,27 @@ msgstr ""
"Syntaks: kbxutil [tilvalg] [filer]\n"
"Vis, eksporter, importer Keybox-data\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+"||Indtast venligst PIN'en for nøglen til at oprette kvalificerede "
+"underskrifter."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Indtast venligst PIn'en for standardnøglerne."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "RSA-modulus mangler eller har ikke størrelsen %d bit\n"
@@ -6574,9 +6601,6 @@ msgstr "NullPIN'en er endnu ikke ændret\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Indtast venligst en ny PIN for standardnøglerne."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Indtast venligst PIn'en for standardnøglerne."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr ""
"|NP|Indtast venligst en ny PIN Unblocking Code (PUK) for standardnøglerne."
@@ -6589,11 +6613,6 @@ msgstr ""
"|N|Indtast venligst en ny PIN for nøglen til at oprette kvalificerede "
"underskrifter."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-"||Indtast venligst PIN'en for nøglen til at oprette kvalificerede "
-"underskrifter."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6653,16 +6672,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "bruger standard-PIN som %s\n"
@@ -6926,6 +6935,10 @@ msgid "certificate policy not allowed"
msgstr "certifikatpolitik er ikke tilladt"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "kunne ikke indhente fingeraftrykket\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "slår udsteder op på ekstern placering\n"
@@ -6933,6 +6946,11 @@ msgstr "slår udsteder op på ekstern placering\n"
msgid "number of issuers matching: %d\n"
msgstr "antallet af udstedere der matcher: %d\n"
+#, fuzzy, c-format
+#| msgid "can't access `%s': %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "kan ikke tilgå »%s«: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "slår udsteder op fra Dirmngr-mellemlageret\n"
@@ -7551,10 +7569,6 @@ msgid "error reading input: %s\n"
msgstr "fejl ved læsning af inddata: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "kunne ikke indhente fingeraftrykket\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "problem under udkig efter eksisterende certifikat: %s\n"
@@ -7646,9 +7660,10 @@ msgstr "Underskrift lavet "
msgid "[date not given]"
msgstr "[dato ikke angivet]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " bruger certifikat-id 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "algoritme: %s"
#, c-format
msgid ""
@@ -8021,15 +8036,6 @@ msgstr ""
msgid "error getting data from cache file: %s\n"
msgstr "fejl ved indhentelse af gemte flag: %s\n"
-#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "ugyldig hash-algoritme »%s«\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr ""
@@ -8040,6 +8046,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "iconv_open mislykkedes: %s:\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "ugyldig hash-algoritme »%s«\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
#| msgid "receiving line failed: %s\n"
msgid "creating S-expression failed: %s\n"
msgstr "modtagelse af linje mislykkedes: %s\n"
@@ -8917,11 +8932,6 @@ msgstr "fejl ved lagring af certifikat\n"
msgid "failed to allocate OCSP context: %s\n"
msgstr "kunne ikke allokere keyDB-håndtag\n"
-#, fuzzy, c-format
-#| msgid "can't access `%s': %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "kan ikke tilgå »%s«: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9560,6 +9570,9 @@ msgstr ""
"Syntaks: gpg-check-pattern [tilvalg] mønsterfil\n"
"Kontroller en adgangsfrase angivet på stdin mod mønsterfilen\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " bruger certifikat-id 0x%08lX\n"
+
#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
diff --git a/po/de.po b/po/de.po
index 1ad7f35..00b6993 100644
--- a/po/de.po
+++ b/po/de.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gnupg-2.1.0\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2020-03-19 14:27+0100\n"
+"PO-Revision-Date: 2020-07-09 11:31+0200\n"
"Last-Translator: Werner Koch <wk@gnupg.org>\n"
"Language-Team: German <de@li.org>\n"
"Language: de\n"
@@ -101,6 +101,9 @@ msgstr "Keine Ãœbereinstimmung - bitte nochmal versuchen."
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (Versuch %d von %d)"
@@ -3544,6 +3547,9 @@ msgstr "\"%s\" ist kein gültiger Fingerabdruck\n"
msgid "subkey \"%s\" not found\n"
msgstr "Unterschlüssel \"%s\" nicht gefunden\n"
+msgid "AEAD: "
+msgstr "AEAD: "
+
msgid "Digest: "
msgstr "Digest: "
@@ -6300,6 +6306,27 @@ msgstr ""
"Syntax: kbxutil [Optionen] [Dateien]\n"
"Anlisten exportieren und Importieren von KeyBox Dateien\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr "%sNummer: %s%%0ABesitzer: %s%s"
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr "Verbliebene Versuche: %d"
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+"||Bitte geben Sie die PIN für den Schlüssel zur Erstellung qualifizierter "
+"Signaturen ein."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Bitte die PIN für den Standard-Schlüssel eingeben."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "Der RSA Modulus fehlt oder ist nicht %d Bits lang\n"
@@ -6319,9 +6346,6 @@ msgstr "Die Nullpin wurde noch nicht geändert\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Bitte eine neue PIN für den Standard-Schlüssel eingeben."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Bitte die PIN für den Standard-Schlüssel eingeben."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr ""
"|NP|Bitte geben Sie einen neuen PIN Entsperrcode (PUK) für den Standard-"
@@ -6336,11 +6360,6 @@ msgstr ""
"|N|Bitte geben Sie eine neue PIN für den Schlüssel zur Erstellung "
"qualifizierter Signaturen ein."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-"||Bitte geben Sie die PIN für den Schlüssel zur Erstellung qualifizierter "
-"Signaturen ein."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6399,16 +6418,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr "%sNummer: %s%%0ABesitzer: %s%%0AAnzahl: %lu%s"
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr "%sNummer: %s%%0ABesitzer: %s%s"
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr "Verbliebene Versuche: %d"
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "Die Standard PIN wird für %s benutzt\n"
@@ -6658,6 +6667,10 @@ msgid "certificate policy not allowed"
msgstr "Die Zertifikatsrichtlinie ist nicht erlaubt"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "Kann den Fingerprint nicht ermitteln\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n"
@@ -6666,6 +6679,10 @@ msgid "number of issuers matching: %d\n"
msgstr "Anzahl der übereinstimmenden Herausgeber: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "authorityInfoAccess kann nicht geholt werden: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "Der Herausgeber wird im Cache des Dirmngr gesucht\n"
@@ -7261,10 +7278,6 @@ msgid "error reading input: %s\n"
msgstr "Fehler beim Lesen der Eingabe: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "Kann den Fingerprint nicht ermitteln\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "Problem bei der Suche nach vorhandenem Zertifikat: %s\n"
@@ -7359,8 +7372,8 @@ msgid "[date not given]"
msgstr "[Datum nicht vorhanden]"
#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " mittels Zertifikat ID 0x%08lX\n"
+msgid "algorithm:"
+msgstr "Verfahren:"
#, c-format
msgid ""
@@ -7708,14 +7721,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "Fehler beim Holen der Daten aus der Zwischenspeicherdatei: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "Ungültige Hashmethode `%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "gcry_md_open für Methode %d fehlgeschlagen: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "Ungültige S-Expression von Libksba erhalten\n"
@@ -7724,6 +7729,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "Konvertierung der S-Expression fehlgeschlagen: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "Ungültige Hashmethode `%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "gcry_md_open für Methode %d fehlgeschlagen: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "Erzeugen der S-Expression fehlgeschlagen: %s\n"
@@ -8488,10 +8501,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "Fehler beim Bereitstellen eines OCSP Kontext: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "authorityInfoAccess kann nicht geholt werden: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "Kein voreingestellter OCSP Responder definiert\n"
@@ -9064,6 +9073,9 @@ msgstr ""
"Syntax: gpg-check-pattern [optionen] Musterdatei\n"
"Die von stdin gelesene Passphrase gegen die Musterdatei prüfen\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " mittels Zertifikat ID 0x%08lX\n"
+
#, fuzzy
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/el.po b/po/el.po
index 7dcc708..f4f620d 100644
--- a/po/el.po
+++ b/po/el.po
@@ -96,6 +96,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3715,6 +3718,9 @@ msgstr "σφάλμα: μη έγκυÏο αποτÏπωμα\n"
msgid "subkey \"%s\" not found\n"
msgstr "το κλειδί '%s' δε βÏέθηκε: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "ΠεÏίληψη: "
@@ -6474,6 +6480,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "ΧÏήση: gpg [επιλογές] [αÏχεία] (-h για βοήθεια)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "αλλαγή της φÏάσης κλειδί"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6495,10 +6521,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "αλλαγή της φÏάσης κλειδί"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "αλλαγή της φÏάσης κλειδί"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "ΠαÏακαλώ επιλέξτε την αιτία για την ανάκληση:\n"
@@ -6509,9 +6531,6 @@ msgstr "ΠαÏακαλώ επιλέξτε την αιτία για την ανά
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6567,16 +6586,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6832,6 +6841,10 @@ msgstr "εγγÏαφή του Î¼Ï…ÏƒÏ„Î¹ÎºÎ¿Ï ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï ÏƒÏ„Î¿ `%s'\n"
msgid "certificate policy not allowed"
msgstr "εγγÏαφή του Î¼Ï…ÏƒÏ„Î¹ÎºÎ¿Ï ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï ÏƒÏ„Î¿ `%s'\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "αποτυχία αÏχικοποίησης της TrustDB: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6840,6 +6853,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: αδυναμία Ï€Ïόσβασης: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7447,10 +7465,6 @@ msgstr "σφάλμα στη δημιουÏγία της φÏάσης κλειδÎ
msgid "error reading input: %s\n"
msgstr "σφάλμα κατά την ανάγνωση του `%s': %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "αποτυχία αÏχικοποίησης της TrustDB: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7530,8 +7544,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "σφάλμα στη δημιουÏγία της φÏάσης κλειδί: %s\n"
+msgid "algorithm:"
+msgstr "θωÏάκιση: %s\n"
#, c-format
msgid ""
@@ -7863,15 +7877,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "σφάλμα στη δημιουÏγία της φÏάσης κλειδί: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "μη έγκυÏος αλγόÏιθμος hash `%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "μη έγκυÏη απάντηση από τον agent\n"
@@ -7881,6 +7886,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "αδυναμία Ï€Ïόσβασης του αÏχείου: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "μη έγκυÏος αλγόÏιθμος hash `%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "διαγÏαφή block κλειδιών απέτυχε: %s\n"
@@ -8663,11 +8677,6 @@ msgstr "δημιουÏγία ενός Ï€Î¹ÏƒÏ„Î¿Ï€Î¿Î¹Î·Ï„Î¹ÎºÎ¿Ï Î±Î½Î¬ÎºÎ»Î·Ï
msgid "failed to allocate OCSP context: %s\n"
msgstr "αποτυχία αÏχικοποίησης της TrustDB: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: αδυναμία Ï€Ïόσβασης: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9262,6 +9271,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "σφάλμα στη δημιουÏγία της φÏάσης κλειδί: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/eo.po b/po/eo.po
index ae5ed19..323e9e3 100644
--- a/po/eo.po
+++ b/po/eo.po
@@ -96,6 +96,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3687,6 +3690,9 @@ msgstr "%s: nevalida dosiero-versio %d\n"
msgid "subkey \"%s\" not found\n"
msgstr "Ålosilo '%s' ne trovita: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr ""
@@ -6389,6 +6395,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Uzado: gpg [opcioj] [dosieroj] (-h por helpo)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "ÅanÄi la pasfrazon"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6410,10 +6436,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "ÅanÄi la pasfrazon"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "ÅanÄi la pasfrazon"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Kialo por revoko: "
@@ -6424,9 +6446,6 @@ msgstr "Kialo por revoko: "
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6482,16 +6501,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6748,6 +6757,10 @@ msgstr "skribas sekretan Ålosilon al '%s'\n"
msgid "certificate policy not allowed"
msgstr "skribas sekretan Ålosilon al '%s'\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "malsukcesis doni komencajn valorojn al fido-datenaro: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6756,6 +6769,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: ne povas aliri: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7370,10 +7388,6 @@ msgstr "eraro dum kreado de pasfrazo: %s\n"
msgid "error reading input: %s\n"
msgstr "eraro dum legado de '%s': %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "malsukcesis doni komencajn valorojn al fido-datenaro: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7453,8 +7467,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "eraro dum kreado de pasfrazo: %s\n"
+msgid "algorithm:"
+msgstr "kiraso: %s\n"
#, c-format
msgid ""
@@ -7779,15 +7793,6 @@ msgstr ""
msgid "error getting data from cache file: %s\n"
msgstr "eraro dum kreado de pasfrazo: %s\n"
-#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "nevalida kompendi-metodo '%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr ""
@@ -7798,6 +7803,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "ÅanÄo de permesoj de '%s' malsukcesis: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "nevalida kompendi-metodo '%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
#| msgid "changing permission of `%s' failed: %s\n"
msgid "creating S-expression failed: %s\n"
msgstr "ÅanÄo de permesoj de '%s' malsukcesis: %s\n"
@@ -8578,11 +8592,6 @@ msgstr "Bona atestilo"
msgid "failed to allocate OCSP context: %s\n"
msgstr "malsukcesis doni komencajn valorojn al fido-datenaro: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: ne povas aliri: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9176,6 +9185,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "eraro dum kreado de pasfrazo: %s\n"
+
+#, fuzzy
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
#~ msgstr "Tiu komando ne eblas en la reÄimo %s.\n"
diff --git a/po/es.po b/po/es.po
index e04efba..23a9483 100644
--- a/po/es.po
+++ b/po/es.po
@@ -106,6 +106,9 @@ msgstr "no coincide - reinténtelo"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (intento %d de %d)"
@@ -3509,6 +3512,9 @@ msgstr "\"%s\" no es una huella digital válida\n"
msgid "subkey \"%s\" not found\n"
msgstr "subclave \"%s\" no encontrada\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Resumen: "
@@ -6202,6 +6208,25 @@ msgstr ""
"Sintaxis: kbxutil [opciones] [ficheros]\n"
"Listar, exportar, importar datos Keybox\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr "%sNúmero: %s%%0ATitular: %s%s"
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr "Intentos disponibles: %d"
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr "||Introduzca un PIN para la clave que crea firmas cualificadas."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Por favor, introduzca PIN para claves estándar."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "falta el módulo RSA o no es de %d bits\n"
@@ -6221,9 +6246,6 @@ msgstr "el PIN-Nulo no ha sido cambiado\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Por favor introduzca un nuevo PIN para las claves estándar."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Por favor, introduzca PIN para claves estándar."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "|NP|Introduzca nuevo PIN Unblocking Code (PUK) para claves estándar."
@@ -6234,9 +6256,6 @@ msgstr ""
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr "|N|Entre un nuevo PIN para la clave que crea firmas cualificadas."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr "||Introduzca un PIN para la clave que crea firmas cualificadas."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6295,16 +6314,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr "%sNúmero: %s%%0ATitular: %s%s"
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr "Intentos disponibles: %d"
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "usando PIN por defecto %s\n"
@@ -6553,6 +6562,10 @@ msgid "certificate policy not allowed"
msgstr "no se permite política de certificado"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "fallo obteniendo huella digital\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "buscando al emisor en una localización externa\n"
@@ -6561,6 +6574,10 @@ msgid "number of issuers matching: %d\n"
msgstr "numero de emisores coincidentes: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "no se ha podido obtener authorityInfoAccess: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "buscando emisor en el caché de Dirmngr\n"
@@ -7149,10 +7166,6 @@ msgid "error reading input: %s\n"
msgstr "error al leer la entrada: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "fallo obteniendo huella digital\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "problema buscando el certificado existente: %s\n"
@@ -7240,9 +7253,10 @@ msgstr "Firmado el "
msgid "[date not given]"
msgstr "[no hay fecha]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " usando el certificado ID 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "algoritmo: %s"
#, c-format
msgid ""
@@ -7573,14 +7587,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "error al obtener datos del archivo de cache: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "algoritmo hash inválido '%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "gcry_md_open para algoritmo %d ha fallado: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "respuesta S-expression de libksba no válida\n"
@@ -7589,6 +7595,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "he fallado al convertir la expresión S-expression: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "algoritmo hash inválido '%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "gcry_md_open para algoritmo %d ha fallado: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "fallo al crear S-expression: %s\n"
@@ -8356,10 +8370,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "fallo al asignar el contexto OCSP: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "no se ha podido obtener authorityInfoAccess: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "no hay un OCSP responder predeterminado\n"
@@ -8948,6 +8958,9 @@ msgstr ""
"Compara frase contraseña dada en entrada estándar con un fichero de "
"patrones\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " usando el certificado ID 0x%08lX\n"
+
#, fuzzy
#~| msgid "option '%s' may not be used in %s mode\n"
#~ msgid ""
diff --git a/po/et.po b/po/et.po
index cf5e858..fbc3510 100644
--- a/po/et.po
+++ b/po/et.po
@@ -93,6 +93,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3687,6 +3690,9 @@ msgstr "viga: vigane sõrmejälg\n"
msgid "subkey \"%s\" not found\n"
msgstr "võtit '%s' ei leitud: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Teatelühend: "
@@ -6395,6 +6401,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Kasuta: gpg [võtmed] [failid] (-h näitab abiinfot)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "muuda parooli"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6416,10 +6442,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "muuda parooli"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "muuda parooli"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Palun valige tühistamise põhjus:\n"
@@ -6430,9 +6452,6 @@ msgstr "Palun valige tühistamise põhjus:\n"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6488,16 +6507,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6753,6 +6762,10 @@ msgstr "kirjutan salajase võtme faili `%s'\n"
msgid "certificate policy not allowed"
msgstr "kirjutan salajase võtme faili `%s'\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "TrustDB initsialiseerimine ebaõnnestus: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6761,6 +6774,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: ei õnnestu kasutada: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7367,10 +7385,6 @@ msgstr "viga parooli loomisel: %s\n"
msgid "error reading input: %s\n"
msgstr "viga `%s' lugemisel: %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "TrustDB initsialiseerimine ebaõnnestus: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7450,8 +7464,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "viga parooli loomisel: %s\n"
+msgid "algorithm:"
+msgstr "pakend: %s\n"
#, c-format
msgid ""
@@ -7781,15 +7795,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "viga parooli loomisel: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "vigane räsialgoritm `%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "vigane vastus agendilt\n"
@@ -7799,6 +7804,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "faili ei õnnestu avada: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "vigane räsialgoritm `%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "võtmebloki kustutamine ebaõnnestus: %s\n"
@@ -8579,11 +8593,6 @@ msgstr "genereeri tühistamise sertifikaat"
msgid "failed to allocate OCSP context: %s\n"
msgstr "TrustDB initsialiseerimine ebaõnnestus: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: ei õnnestu kasutada: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9178,6 +9187,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "viga parooli loomisel: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/fi.po b/po/fi.po
index 05e7d4d..ffca851 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -109,6 +109,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3707,6 +3710,9 @@ msgstr "virhe: sormenjälki on väärä\n"
msgid "subkey \"%s\" not found\n"
msgstr "avainta \"%s\" ei löydy: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Tiiviste: "
@@ -6454,6 +6460,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Käyttö: gpg [valitsimet] [tiedostot] (-h näyttää ohjeen)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "muuta salasanaa"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6475,10 +6501,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "muuta salasanaa"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "muuta salasanaa"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Valitse mitätöinnin syy:\n"
@@ -6489,9 +6511,6 @@ msgstr "Valitse mitätöinnin syy:\n"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6547,16 +6566,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6813,6 +6822,10 @@ msgstr "kirjoitan salaisen avaimen kohteeseen \"%s\"\n"
msgid "certificate policy not allowed"
msgstr "kirjoitan salaisen avaimen kohteeseen \"%s\"\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "TrustDB:n alustaminen ei onnistu: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6821,6 +6834,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: kohteeseen ei päästä: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7427,10 +7445,6 @@ msgstr "virhe luotaessa salasanaa: %s\n"
msgid "error reading input: %s\n"
msgstr "virhe luettaessa tiedostoa \"%s\": %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "TrustDB:n alustaminen ei onnistu: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7510,8 +7524,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "virhe luotaessa salasanaa: %s\n"
+msgid "algorithm:"
+msgstr "ascii-koodaus: %s\n"
#, c-format
msgid ""
@@ -7842,15 +7856,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "virhe luotaessa salasanaa: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "virheellinen tiivistealgoritmi \"%s\"\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "agentin lähettämä vastaus ei kelpaa\n"
@@ -7860,6 +7865,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "ei voi avata tiedostoa: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "virheellinen tiivistealgoritmi \"%s\"\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "avainlohkojen poisto epäonnistui: %s\n"
@@ -8642,11 +8656,6 @@ msgstr "luo mitätöintivarmenne"
msgid "failed to allocate OCSP context: %s\n"
msgstr "TrustDB:n alustaminen ei onnistu: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: kohteeseen ei päästä: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9241,6 +9250,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "virhe luotaessa salasanaa: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/fr.po b/po/fr.po
index 84cceb9..1d753b1 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -108,6 +108,9 @@ msgstr "ne correspond pas — veuillez réessayer"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (essai %d sur %d)"
@@ -3650,6 +3653,9 @@ msgstr "« %s » n’est pas une empreinte\n"
msgid "subkey \"%s\" not found\n"
msgstr "clef « %s » introuvable : %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Hachage : "
@@ -6469,6 +6475,27 @@ msgstr ""
"Syntaxe : kbxutil [options] [fichiers]\n"
"Afficher, exporter, importer les données de trousseau local\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+"||Veuillez entrer le code personnel pour permettre à la clef de créer des "
+"signatures qualifiées."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Veuillez entrer le code personnel pour les clefs standards."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "le module RSA est manquant ou sa taille n'est pas de %d bits\n"
@@ -6488,9 +6515,6 @@ msgstr "le code personnel nul n'a pas encore été modifié\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Veuillez entrer un nouveau code personnel pour les clefs standards."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Veuillez entrer le code personnel pour les clefs standards."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr ""
"|NP|Veuillez entrer un nouveau code de déblocage personnel (CDP) pour les "
@@ -6506,11 +6530,6 @@ msgstr ""
"|N|Veuillez entrer un nouveau code personnel pour permettre à la clef de "
"créer des signatures qualifiées."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-"||Veuillez entrer le code personnel pour permettre à la clef de créer des "
-"signatures qualifiées."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6570,16 +6589,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "utilisation du code personnel par défaut en tant que %s\n"
@@ -6849,6 +6858,10 @@ msgid "certificate policy not allowed"
msgstr "politique de certificat non autorisée"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "impossible d'obtenir l'empreinte\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "recherche d'émetteur à l'extérieur\n"
@@ -6857,6 +6870,10 @@ msgid "number of issuers matching: %d\n"
msgstr "nombre d'émetteurs correspondants : %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "impossible d'obtenir authorityInfoAccess : %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "recherche d'émetteur dans le cache du Dirmngr\n"
@@ -7452,10 +7469,6 @@ msgid "error reading input: %s\n"
msgstr "erreur de lecture de l'entrée : %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "impossible d'obtenir l'empreinte\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "problème de recherche de certificat existant : %s\n"
@@ -7550,9 +7563,10 @@ msgstr "Signature faite le "
msgid "[date not given]"
msgstr "[date non donnée]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " en utilisant le certificat d'identifiant 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "algorithme : %s"
#, c-format
msgid ""
@@ -7898,14 +7912,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "erreur de lecture des données du fichier de cache : %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "algorithme de hachage « %s » inconnu\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "échec de gcry_md_open pour l'algorithme %d : %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "expression symbolique incorrecte obtenue de libksba\n"
@@ -7914,6 +7920,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "échec de conversion d'expression symbolique : %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "algorithme de hachage « %s » inconnu\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "échec de gcry_md_open pour l'algorithme %d : %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "échec de création d'expression symbolique : %s\n"
@@ -8712,10 +8726,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "échec d'allocation du contexte OCSP : %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "impossible d'obtenir authorityInfoAccess : %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "aucun répondeur OCSP par défaut défini\n"
@@ -9321,6 +9331,9 @@ msgstr ""
"Vérifier une phrase secrète donnée sur l'entrée standard par rapport à "
"ficmotif\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " en utilisant le certificat d'identifiant 0x%08lX\n"
+
#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
diff --git a/po/gl.po b/po/gl.po
index 0362895..396e8b7 100644
--- a/po/gl.po
+++ b/po/gl.po
@@ -94,6 +94,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3711,6 +3714,9 @@ msgstr "erro: pegada dactilar non válida\n"
msgid "subkey \"%s\" not found\n"
msgstr "non se atopou a chave `%s': %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Resumo: "
@@ -6458,6 +6464,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Uso: gpg [opcións] [ficheiros] (-h para ve-la axuda)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "cambia-lo contrasinal"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6479,10 +6505,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "cambia-lo contrasinal"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "cambia-lo contrasinal"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Por favor, escolla o motivo da revocación:\n"
@@ -6493,9 +6515,6 @@ msgstr "Por favor, escolla o motivo da revocación:\n"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6551,16 +6570,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6817,6 +6826,10 @@ msgstr "gravando a chave secreta en `%s'\n"
msgid "certificate policy not allowed"
msgstr "gravando a chave secreta en `%s'\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "non se puido inicializa-la base de datos de confianzas: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6825,6 +6838,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: non é posible acceder: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7439,10 +7457,6 @@ msgstr "erro ao crea-lo contrasinal: %s\n"
msgid "error reading input: %s\n"
msgstr "erro lendo `%s': %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "non se puido inicializa-la base de datos de confianzas: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7522,8 +7536,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "erro ao crea-lo contrasinal: %s\n"
+msgid "algorithm:"
+msgstr "armadura: %s\n"
#, c-format
msgid ""
@@ -7854,15 +7868,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "erro ao crea-lo contrasinal: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "algoritmo de hash non válido `%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "resposta do axente non válida\n"
@@ -7873,6 +7878,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "o cambio de permisos de `%s' fallou: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "algoritmo de hash non válido `%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
#| msgid "changing permission of `%s' failed: %s\n"
msgid "creating S-expression failed: %s\n"
msgstr "o cambio de permisos de `%s' fallou: %s\n"
@@ -8658,11 +8672,6 @@ msgstr "Certificado correcto"
msgid "failed to allocate OCSP context: %s\n"
msgstr "non se puido inicializa-la base de datos de confianzas: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: non é posible acceder: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9259,6 +9268,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "erro ao crea-lo contrasinal: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/hu.po b/po/hu.po
index edde068..36c342a 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -1,12 +1,12 @@
# GnuPG Hungarian translation.
-# Copyright (C) 2003, 2004 Free Software Foundation, Inc.
-# Nagy Ferenc László <nfl@nfllab.com>, 2003, 2004.
+# Copyright (C) 2003, 2004, 2020 Free Software Foundation, Inc.
+# Nagy Ferenc László <nfl@nfllab.com>, 2003, 2004, 2020.
#
msgid ""
msgstr ""
-"Project-Id-Version: gnupg 1.2.5\n"
+"Project-Id-Version: gnupg 2.2.20\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2004-06-19 21:53+0200\n"
+"PO-Revision-Date: 2020-06-09 23:10+0200\n"
"Last-Translator: Nagy Ferenc László <nfl@nfllab.com>\n"
"Language-Team: Hungarian <translation-team-hu@lists.sourceforge.net>\n"
"Language: hu\n"
@@ -93,6 +93,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3686,6 +3689,9 @@ msgstr "Hiba: Érvénytelen ujjlenyomat.\n"
msgid "subkey \"%s\" not found\n"
msgstr "\"%s\" kulcs nem található: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Kivonat: "
@@ -4397,16 +4403,11 @@ msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
msgstr ""
"(N)év, (M)egjegyzés, (E)-mail megváltoztatása vagy (R)endben/(K)ilépés? "
-#, fuzzy
-#| msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? "
msgid "Change (N)ame, (E)mail, or (Q)uit? "
-msgstr "(N)év, (M)egjegyzés, (E)-mail megváltoztatása vagy (K)ilépés? "
+msgstr "(N)év, (E)-mail megváltoztatása vagy (K)ilépés? "
-#, fuzzy
-#| msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
msgid "Change (N)ame, (E)mail, or (O)kay/(Q)uit? "
-msgstr ""
-"(N)év, (M)egjegyzés, (E)-mail megváltoztatása vagy (R)endben/(K)ilépés? "
+msgstr "(N)év, (E)-mail megváltoztatása vagy (R)endben/(K)ilépés? "
msgid "Please correct the error first\n"
msgstr "Kérem, előbb javítsa ki a hibát!\n"
@@ -6424,6 +6425,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Használat: gpg [opciók] [fájlok] (-h a súgóhoz)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "jelszóváltoztatás"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6445,10 +6466,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "jelszóváltoztatás"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "jelszóváltoztatás"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Kérem, válassza ki a visszavonás okát:\n"
@@ -6459,9 +6476,6 @@ msgstr "Kérem, válassza ki a visszavonás okát:\n"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6517,16 +6531,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6782,6 +6786,10 @@ msgstr "Ãrom a titkos kulcsot a %s állományba.\n"
msgid "certificate policy not allowed"
msgstr "Ãrom a titkos kulcsot a %s állományba.\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "Bizalmi adatbázis (%s) inicializálása sikertelen!\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6790,6 +6798,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: Nem tudom elérni: %s.\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7397,10 +7410,6 @@ msgstr "Hiba a jelszó létrehozásakor: %s.\n"
msgid "error reading input: %s\n"
msgstr "Hiba \"%s\" olvasásakor: %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "Bizalmi adatbázis (%s) inicializálása sikertelen!\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7480,8 +7489,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "Hiba a jelszó létrehozásakor: %s.\n"
+msgid "algorithm:"
+msgstr "Páncél: %s\n"
#, c-format
msgid ""
@@ -7811,15 +7820,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "Hiba a jelszó létrehozásakor: %s.\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "Érvénytelen kivonatoló algoritmus: %s\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "Érvénytelen válasz az ügynöktől!\n"
@@ -7829,6 +7829,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "Nem tudom megnyitni az állományt: %s.\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "Érvénytelen kivonatoló algoritmus: %s\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "A kulcsblokk törlése sikertelen: %s.\n"
@@ -8609,11 +8618,6 @@ msgstr "visszavonási igazolás készítése"
msgid "failed to allocate OCSP context: %s\n"
msgstr "Bizalmi adatbázis (%s) inicializálása sikertelen!\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: Nem tudom elérni: %s.\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9208,6 +9212,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "Hiba a jelszó létrehozásakor: %s.\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/id.po b/po/id.po
index 3f60baf..9fd5575 100644
--- a/po/id.po
+++ b/po/id.po
@@ -98,6 +98,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3691,6 +3694,9 @@ msgstr "kesalahan: fingerprint tidak valid\n"
msgid "subkey \"%s\" not found\n"
msgstr "kunci '%s' tidak ditemukan: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Digest: "
@@ -6417,6 +6423,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Pemakaian: gpg [pilihan] [file] (-h untuk bantuan)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "ubah passphrase"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6438,10 +6464,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "ubah passphrase"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "ubah passphrase"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Silakan pilih alasan untuk pembatalan:\n"
@@ -6452,9 +6474,6 @@ msgstr "Silakan pilih alasan untuk pembatalan:\n"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6510,16 +6529,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6775,6 +6784,10 @@ msgstr "menulis kunci rahasia ke `%s'\n"
msgid "certificate policy not allowed"
msgstr "menulis kunci rahasia ke `%s'\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "gagal inisialisasi TrustDB: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6783,6 +6796,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: tidak dapat mengakses: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7390,10 +7408,6 @@ msgstr "kesalahan penciptaan passphrase: %s\n"
msgid "error reading input: %s\n"
msgstr "kesalahan membaca `%s': %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "gagal inisialisasi TrustDB: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7473,8 +7487,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "kesalahan penciptaan passphrase: %s\n"
+msgid "algorithm:"
+msgstr "armor: %s\n"
#, c-format
msgid ""
@@ -7804,15 +7818,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "kesalahan penciptaan passphrase: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "algoritma hash tidak valid `%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "respon tidak valid dari agen\n"
@@ -7822,6 +7827,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "tidak dapat membuka file: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "algoritma hash tidak valid `%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "gagal menghapus keyblok: %s\n"
@@ -8602,11 +8616,6 @@ msgstr "buat sertifikat revokasi"
msgid "failed to allocate OCSP context: %s\n"
msgstr "gagal inisialisasi TrustDB: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: tidak dapat mengakses: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9201,6 +9210,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "kesalahan penciptaan passphrase: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/it.po b/po/it.po
index d61e748..08d32bf 100644
--- a/po/it.po
+++ b/po/it.po
@@ -93,6 +93,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3698,6 +3701,9 @@ msgstr "errore: impronta digitale non valida\n"
msgid "subkey \"%s\" not found\n"
msgstr "chiave `%s' non trovata: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Digest: "
@@ -6456,6 +6462,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Uso: gpg [opzioni] [files] (-h per l'aiuto)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "cambia la passphrase"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6477,10 +6503,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "cambia la passphrase"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "cambia la passphrase"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Per favore scegli il motivo della revoca:\n"
@@ -6491,9 +6513,6 @@ msgstr "Per favore scegli il motivo della revoca:\n"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6549,16 +6568,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6814,6 +6823,10 @@ msgstr "scrittura della chiave segreta in `%s'\n"
msgid "certificate policy not allowed"
msgstr "scrittura della chiave segreta in `%s'\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "inizializzazione del trustdb fallita: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6822,6 +6835,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: impossibile acedere a: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7428,10 +7446,6 @@ msgstr "errore nella creazione della passhprase: %s\n"
msgid "error reading input: %s\n"
msgstr "errore leggendo `%s': %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "inizializzazione del trustdb fallita: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7511,8 +7525,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "errore nella creazione della passhprase: %s\n"
+msgid "algorithm:"
+msgstr "armatura: %s\n"
#, c-format
msgid ""
@@ -7843,15 +7857,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "errore nella creazione della passhprase: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "algoritmo di hash non valido `%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "risposta non valida dall'agent\n"
@@ -7861,6 +7866,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "impossibile aprire il file: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "algoritmo di hash non valido `%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "cancellazione del keyblock fallita: %s\n"
@@ -8643,11 +8657,6 @@ msgstr "genera un certificato di revoca"
msgid "failed to allocate OCSP context: %s\n"
msgstr "inizializzazione del trustdb fallita: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: impossibile acedere a: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9242,6 +9251,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "errore nella creazione della passhprase: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/ja.po b/po/ja.po
index 27680f7..59a9845 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gnupg 2.2.20\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2020-03-19 09:27+0900\n"
+"PO-Revision-Date: 2020-07-07 09:37+0900\n"
"Last-Translator: NIIBE Yutaka <gniibe@fsij.org>\n"
"Language-Team: none\n"
"Language: ja\n"
@@ -97,6 +97,9 @@ msgstr "一致ã—ã¾ã›ã‚“ - ã‚‚ã†ä¸€åº¦"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (ç¾åœ¨ %d / 最大 %d)"
@@ -3423,6 +3426,9 @@ msgstr "\"%s\"ã¯æ­£ã—ã„フィンガープリントã§ã¯ã‚ã‚Šã¾ã›ã‚“\n"
msgid "subkey \"%s\" not found\n"
msgstr "副éµ\"%s\"ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“\n"
+msgid "AEAD: "
+msgstr "AEAD: "
+
msgid "Digest: "
msgstr "ダイジェスト: "
@@ -5998,6 +6004,25 @@ msgstr ""
"å½¢å¼: kbxutil [オプション] [ファイル]\n"
"Keyboxデータを一覧ã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆ\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr "%s番å·: %s%%0Aä¿æŒè€…: %s%s"
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr "残ã•ã‚ŒãŸè©¦è¡Œå›žæ•°: %d"
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr "||æ–°ã—ã„PINã‚’èªå®šç½²åを生æˆã™ã‚‹éµã®ãŸã‚ã«å…¥åŠ›ã—ã¦ãã ã•ã„。"
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||PINを標準ã®éµã®ãŸã‚ã«å…¥åŠ›ã—ã¦ãã ã•ã„。"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "RSAã®ãƒ¢ã‚¸ãƒ¥ãƒ©ã‚¹ãŒãªã„ã‹ã€%dビットã®ã‚‚ã®ã§ã¯ã‚ã‚Šã¾ã›ã‚“\n"
@@ -6017,9 +6042,6 @@ msgstr "NullPINãŒå¤‰æ›´ã•ã‚Œã¦ã„ã¾ã›ã‚“\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|æ–°ã—ã„PINを標準ã®éµã®ãŸã‚ã«å…¥åŠ›ã—ã¦ãã ã•ã„。"
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||PINを標準ã®éµã®ãŸã‚ã«å…¥åŠ›ã—ã¦ãã ã•ã„。"
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "|NP|標準ã®éµã®æ–°ã—ã„PIN Unblocking Code (PUK)を入力ã—ã¦ãã ã•ã„。"
@@ -6029,9 +6051,6 @@ msgstr "|P|標準ã®éµã®PIN Unblocking Code (PUK)を入力ã—ã¦ãã ã•ã„ã€
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr "|N|æ–°ã—ã„PINã‚’èªå®šç½²åを生æˆã™ã‚‹éµã®ãŸã‚ã«å…¥åŠ›ã—ã¦ãã ã•ã„。"
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr "||æ–°ã—ã„PINã‚’èªå®šç½²åを生æˆã™ã‚‹éµã®ãŸã‚ã«å…¥åŠ›ã—ã¦ãã ã•ã„。"
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6088,16 +6107,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr "%s番å·: %s%%0Aä¿æŒè€…: %s%%0Aカウンタ: %lu%s"
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr "%s番å·: %s%%0Aä¿æŒè€…: %s%s"
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr "残ã•ã‚ŒãŸè©¦è¡Œå›žæ•°: %d"
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "デフォルトPINã‚’%sã¨ã—ã¦ä½¿ã„ã¾ã™\n"
@@ -6343,6 +6352,10 @@ msgid "certificate policy not allowed"
msgstr "証明書ãƒãƒªã‚·ãƒ¼ã¯èªã‚られã¾ã›ã‚“"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "フィンガープリントã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸ\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "発行者ã®å¤–部ロケーションを調ã¹ã¦ã„ã¾ã™\n"
@@ -6351,6 +6364,10 @@ msgid "number of issuers matching: %d\n"
msgstr "マッãƒã™ã‚‹ç™ºè¡Œè€…ã®æ•°: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "authorityInfoAccessã‚’å–å¾—ã§ãã¾ã›ã‚“: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "Dirmngrキャッシュã‹ã‚‰ç™ºè¡Œè€…を調ã¹ã¦ã„ã¾ã™\n"
@@ -6933,10 +6950,6 @@ msgid "error reading input: %s\n"
msgstr "入力読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "フィンガープリントã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸ\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "既存ã®è¨¼æ˜Žæ›¸ã®æ¤œç´¢ã®å•é¡Œ: %s\n"
@@ -7028,8 +7041,8 @@ msgid "[date not given]"
msgstr "[日時指定ãªã—]"
#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " 証明書 ID 0x%08lXを用ã„ã¾ã™\n"
+msgid "algorithm:"
+msgstr "アルゴリズム:"
#, c-format
msgid ""
@@ -7353,14 +7366,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "キャッシュ・ファイルã‹ã‚‰ãƒ‡ãƒ¼ã‚¿ã®å–得エラー: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "ä¸æ˜Žãªãƒãƒƒã‚·ãƒ¥ãƒ»ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ '%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "アルゴリズム%dã®gcry_md_openãŒå¤±æ•—: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "libksbaã‹ã‚‰ç„¡åŠ¹ãªS-å¼ã‚’å–å¾—ã—ã¾ã—ãŸ\n"
@@ -7369,6 +7374,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "Så¼ã®å¤‰æ›ã«å¤±æ•—ã—ã¾ã—ãŸ: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "ä¸æ˜Žãªãƒãƒƒã‚·ãƒ¥ãƒ»ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ '%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "アルゴリズム%dã®gcry_md_openãŒå¤±æ•—: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "Så¼ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ: %s\n"
@@ -8119,10 +8132,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "OCSPコンテクストã®ç¢ºä¿ã«å¤±æ•—ã—ã¾ã—ãŸ: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "authorityInfoAccessã‚’å–å¾—ã§ãã¾ã›ã‚“: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "デフォルトOCSPレスãƒãƒ³ãƒ€ãŒå®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“\n"
@@ -8691,6 +8700,9 @@ msgstr ""
"å½¢å¼: gpg-check-pattern [オプション] パターンファイル\n"
"パターンファイルã«å¯¾ã—ã¦æ¨™æº–入力ã®ãƒ‘スフレーズを確èªã™ã‚‹\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " 証明書 ID 0x%08lXを用ã„ã¾ã™\n"
+
#~ msgid "male"
#~ msgstr "ç”·"
diff --git a/po/nb.po b/po/nb.po
index 3ff40cf..3d3c745 100644
--- a/po/nb.po
+++ b/po/nb.po
@@ -101,6 +101,9 @@ msgstr "feil. Prøv igjen"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (forsøk %d av %d)"
@@ -3482,6 +3485,9 @@ msgstr "«%s» er et ugyldig fingeravtrykk\n"
msgid "subkey \"%s\" not found\n"
msgstr "fant ikke undernøkkel «%s»\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Kontrollsum: "
@@ -6148,6 +6154,25 @@ msgstr ""
"Syntaks: kbxutil [valg] [filer]\n"
"Vis, eksporter eller importer Keybox-data\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr "%sNummer\\x1f: %s%%0AHolder\\x1f: %s%s"
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr "Gjenstående forsøk: %d"
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr "||Skriv inn PIN for å la nøkkelen lage kvalifiserte signaturer."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Skriv inn PIN-kode for standardnøkler."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "RSA-modulus mangler eller er av annen størrelse enn %d bit\n"
@@ -6167,9 +6192,6 @@ msgstr "NullPIN er ikke blitt endret enda\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Skriv inn ny PIN-kode for standardnøkler."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Skriv inn PIN-kode for standardnøkler."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "|NP|Skriv inn ny PIN-opplåsingskode (PUK) for standardnøkler."
@@ -6179,9 +6201,6 @@ msgstr "|P|Skriv inn PIN-opplåsingskode (PUK) for standardnøkler."
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr "|N|Skriv inn ny PIN for å la nøkkelen lage kvalifiserte signaturer."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr "||Skriv inn PIN for å la nøkkelen lage kvalifiserte signaturer."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6237,16 +6256,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr "%sNummer\\x1f: %s%%0AHolder\\x1f: %s%%0ATeller\\x1f: %lu%s"
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr "%sNummer\\x1f: %s%%0AHolder\\x1f: %s%s"
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr "Gjenstående forsøk: %d"
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "bruker forvalgt PIN som %s\n"
@@ -6492,6 +6501,10 @@ msgid "certificate policy not allowed"
msgstr "sertifikatregelverk tillates ikke"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "klarte ikke å hente fingeravtrykk\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "slår opp utsteder på ekstern plassering\n"
@@ -6500,6 +6513,10 @@ msgid "number of issuers matching: %d\n"
msgstr "antall ustedere funnet: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "klarte ikke å hente «authorityInfoAccess»: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "slår opp utsteder fra Dirmngr-hurtiglager\n"
@@ -7083,10 +7100,6 @@ msgid "error reading input: %s\n"
msgstr "feil under lesing av inndata: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "klarte ikke å hente fingeravtrykk\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "klarte ikke å søke etter sertifikat: %s\n"
@@ -7176,9 +7189,10 @@ msgstr "Signatur fullført"
msgid "[date not given]"
msgstr "[dato ikke oppgitt]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " ved bruk av sertifikat-ID 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "algoritme: %s"
#, c-format
msgid ""
@@ -7504,14 +7518,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "feil under henting av data fra hurtiglager-fil: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "«%s» er en ugyldig summeringsalgoritme\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "«gcry_md_open» for algoritme %d mislyktes: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "fikk ugyldig S-uttrykk fra libksba\n"
@@ -7520,6 +7526,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "konvertering av S-uttrykk mislyktes: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "«%s» er en ugyldig summeringsalgoritme\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "«gcry_md_open» for algoritme %d mislyktes: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "oppretting av S-uttrykk mislyktes: %s\n"
@@ -8272,10 +8286,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "klarte ikke å tildele OCSP-kontekst: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "klarte ikke å hente «authorityInfoAccess»: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "ingen forvalgt OCSP-svartjeneste\n"
@@ -8850,6 +8860,9 @@ msgstr ""
"Syntaks: gpg-check-pattern [valg] mønsterfil\n"
"Kontroller passordfrase oppgitt på standard innkanal mot valgt mønsterfil\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " ved bruk av sertifikat-ID 0x%08lX\n"
+
#, fuzzy
#~| msgid "option '%s' may not be used in %s mode\n"
#~ msgid ""
diff --git a/po/pl.po b/po/pl.po
index f116b0c..1aa6a9c 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -95,6 +95,9 @@ msgstr "nie pasują - proszę spróbować jeszcze raz"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (próba %d z %d)"
@@ -3500,6 +3503,9 @@ msgstr ",,%s'' nie jest właściwym odciskiem\n"
msgid "subkey \"%s\" not found\n"
msgstr "podklucz ,,%s'' nie został odnaleziony\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Skrót: "
@@ -6249,6 +6255,26 @@ msgstr ""
"Składnia: kbxutil [opcje] [pliki]\n"
"Wypisywanie, eksport, import danych Keybox\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr "%sNumer: %s%%0AWłaściciel: %s%s"
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr "Pozostało prób: %d"
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+"||Proszę wprowadzić PIN PIN dla klucza do tworzenia podpisów kwalifikowanych."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Proszę wprowadzić PIN dla zwykłych kluczy."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "reszta RSA brakująca lub o rozmiarze innym niż %d bity\n"
@@ -6268,9 +6294,6 @@ msgstr "NullPIN nie został jeszcze zmieniony\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Proszę wprowadzić nowy PIN dla zwykłych kluczy."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Proszę wprowadzić PIN dla zwykłych kluczy."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr ""
"|NP|Proszę wprowadzić nowy kod oblokowujący PIN (PUK) dla zwykłych kluczy."
@@ -6283,10 +6306,6 @@ msgstr ""
"|N|Proszę wprowadzić nowy PIN dla klucza do tworzenia podpisów "
"kwalifikowanych."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-"||Proszę wprowadzić PIN PIN dla klucza do tworzenia podpisów kwalifikowanych."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6345,16 +6364,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr "%sNumer: %s%%0AWłaściciel: %s%%0ALicznik: %lu%s"
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr "%sNumer: %s%%0AWłaściciel: %s%s"
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr "Pozostało prób: %d"
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "użycie domyślnego PIN-u jako %s\n"
@@ -6607,6 +6616,10 @@ msgid "certificate policy not allowed"
msgstr "polityka certyfikatu niedozwolona"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "nie udało się pobrać odcisku\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "poszukiwanie wystawcy na zewnÄ…trz\n"
@@ -6615,6 +6628,10 @@ msgid "number of issuers matching: %d\n"
msgstr "liczba pasujących wystawców: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "nie można uzyskać authorityInfoAccess: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "poszukiwanie wystawcy w pamięci podręcznej Dirmngr\n"
@@ -7198,10 +7215,6 @@ msgid "error reading input: %s\n"
msgstr "błąd odczytu wejścia: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "nie udało się pobrać odcisku\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "problem odszukaniem istniejÄ…cego certyfikatu: %s\n"
@@ -7292,9 +7305,10 @@ msgstr "Podpisano w "
msgid "[date not given]"
msgstr "[nie podano daty]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " przy użyciu certyfikatu o ID 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "algorytm: %s"
#, c-format
msgid ""
@@ -7628,14 +7642,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "błąd pobierania danych z pliku pamięci podręcznej: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "niewłaściwy algorytm skrótu ,,%s''\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "gcry_md_open dla algorytmu %d nie powiodło się: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "odebrano błędne S-wyrażenie z libksba\n"
@@ -7644,6 +7650,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "konwersja S-wyrażenia nie powiodła się: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "niewłaściwy algorytm skrótu ,,%s''\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "gcry_md_open dla algorytmu %d nie powiodło się: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "tworzenie S-wyrażenia nie powiodło się: %s\n"
@@ -8404,10 +8418,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "nie udało się przydzielić kontekstu OCSP: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "nie można uzyskać authorityInfoAccess: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "nie zdefiniowano domyślnego respondera OCSP\n"
@@ -8983,6 +8993,9 @@ msgstr ""
"Składnia: gpg-check-pattern [opcje] plik-wzorców\n"
"Sprawdzanie hasła ze standardowego wejścia względem pliku wzorców\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " przy użyciu certyfikatu o ID 0x%08lX\n"
+
#, fuzzy
#~| msgid "option '%s' may not be used in %s mode\n"
#~ msgid ""
diff --git a/po/pt.po b/po/pt.po
index d3d9d7f..b7f7d6f 100644
--- a/po/pt.po
+++ b/po/pt.po
@@ -96,6 +96,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3695,6 +3698,9 @@ msgstr "%s: versão de ficheiro inválida %d\n"
msgid "subkey \"%s\" not found\n"
msgstr "chave `%s' não encontrada: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "'Digest': "
@@ -6413,6 +6419,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Uso: gpg [opções] [ficheiros] (-h para ajuda)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "muda a frase secreta"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6434,10 +6460,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "muda a frase secreta"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "muda a frase secreta"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "motivo da revocação: "
@@ -6448,9 +6470,6 @@ msgstr "motivo da revocação: "
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6506,16 +6525,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6771,6 +6780,10 @@ msgstr "a escrever chave privada para `%s'\n"
msgid "certificate policy not allowed"
msgstr "a escrever chave privada para `%s'\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "falha ao inicializar a base de dados de confiança: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6779,6 +6792,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: impossível aceder: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7389,10 +7407,6 @@ msgstr "erro na criação da frase secreta: %s\n"
msgid "error reading input: %s\n"
msgstr "erro na leitura de `%s': %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "falha ao inicializar a base de dados de confiança: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7472,8 +7486,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "erro na criação da frase secreta: %s\n"
+msgid "algorithm:"
+msgstr "armadura: %s\n"
#, c-format
msgid ""
@@ -7802,6 +7816,14 @@ msgstr ""
msgid "error getting data from cache file: %s\n"
msgstr "erro na criação da frase secreta: %s\n"
+#, c-format
+msgid "got an invalid S-expression from libksba\n"
+msgstr ""
+
+#, fuzzy, c-format
+msgid "converting S-expression failed: %s\n"
+msgstr "impossível abrir %s: %s\n"
+
#, fuzzy, c-format
#| msgid "invalid hash algorithm `%s'\n"
msgid "unknown hash algorithm '%s'\n"
@@ -7811,14 +7833,6 @@ msgstr "algoritmo de dispersão inválido `%s'\n"
msgid "gcry_md_open for algorithm %d failed: %s\n"
msgstr ""
-#, c-format
-msgid "got an invalid S-expression from libksba\n"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "converting S-expression failed: %s\n"
-msgstr "impossível abrir %s: %s\n"
-
#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "remoção do bloco de chave falhou: %s\n"
@@ -8602,11 +8616,6 @@ msgstr "gerar um certificado de revogação"
msgid "failed to allocate OCSP context: %s\n"
msgstr "falha ao inicializar a base de dados de confiança: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: impossível aceder: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9202,6 +9211,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "erro na criação da frase secreta: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/ro.po b/po/ro.po
index 575cde3..54ed771 100644
--- a/po/ro.po
+++ b/po/ro.po
@@ -100,6 +100,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3736,6 +3739,9 @@ msgstr "amprentă invalidă"
msgid "subkey \"%s\" not found\n"
msgstr "cheia \"%s\" nu a fost găsită: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Rezumat: "
@@ -6502,6 +6508,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Folosire: gpg [opţiuni] [fişiere] (-h pentru ajutor)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Vă rugăm introduceţi PIN%%0A[semnături făcute: %lu]"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "modulus-ul RSA lipseşte sau nu are %d biţi\n"
@@ -6523,10 +6549,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "||Vă rugăm introduceţi PIN%%0A[semnături făcute: %lu]"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Vă rugăm introduceţi PIN%%0A[semnături făcute: %lu]"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "||Vă rugăm introduceţi PIN%%0A[semnături făcute: %lu]"
@@ -6537,9 +6559,6 @@ msgstr "||Vă rugăm introduceţi PIN%%0A[semnături făcute: %lu]"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6595,16 +6614,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6866,6 +6875,10 @@ msgstr "exportul cheilor secrete nu este permis\n"
msgid "certificate policy not allowed"
msgstr "exportul cheilor secrete nu este permis\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "am eşuat să stochez amprenta: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6874,6 +6887,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: nu pot accesa: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7486,10 +7504,6 @@ msgstr "eroare la obţinerea numărului serial: %s\n"
msgid "error reading input: %s\n"
msgstr "eroare la citire `%s': %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "am eşuat să stochez amprenta: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7569,8 +7583,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "eroare la obţinerea numărului serial: %s\n"
+msgid "algorithm:"
+msgstr "validitate: %s"
#, c-format
msgid ""
@@ -7904,15 +7918,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "eroare la obţinere noului PIN: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "algoritm hash invalid `%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "răspuns invalid de la agent\n"
@@ -7922,6 +7927,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "nu pot deschide fiÅŸierul: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "algoritm hash invalid `%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "citirea cheii publice a eÅŸuat: %s\n"
@@ -8724,11 +8738,6 @@ msgstr "generează un certificat de revocare"
msgid "failed to allocate OCSP context: %s\n"
msgstr "am eşuat să stochez cheia: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: nu pot accesa: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9327,6 +9336,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "eroare la obţinerea numărului serial: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/ru.po b/po/ru.po
index c56c60c..d48299f 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -98,6 +98,9 @@ msgstr "не подходит - попробуйте еще раз"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (попытка %d из %d)"
@@ -3495,6 +3498,9 @@ msgstr "\"%s\" - не правильный отпечаток\n"
msgid "subkey \"%s\" not found\n"
msgstr "подключ \"%s\" не найден\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Хеш: "
@@ -6213,6 +6219,25 @@ msgstr ""
"СинтакÑиÑ: kbxutil [параметры] [файлы]\n"
"ПроÑмотр, ÑкÑпорт, импорт данных щита Ñ ÐºÐ»ÑŽÑ‡Ð°Ð¼Ð¸\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr "%sÐомер: %s%%0AДержатель: %s%s"
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr "ОÑталоÑÑŒ попыток: %d"
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr "||Введите PIN ключа Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ²Ð°Ð»Ð¸Ñ„Ð¸Ñ†Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ñ… подпиÑей."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "|A|Введите PIN Ð´Ð»Ñ Ñтандартных ключей."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "Модули RSA пропущены, или их размер не равен %d бит\n"
@@ -6232,9 +6257,6 @@ msgstr "пуÑтой PIN до Ñих пор не изменен\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|A|Введите новый PIN Ð´Ð»Ñ Ñтандартных ключей."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "|A|Введите PIN Ð´Ð»Ñ Ñтандартных ключей."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "|NP|Введите новый код разблокировки PIN (PUK) Ð´Ð»Ñ Ñтандартных ключей."
@@ -6244,9 +6266,6 @@ msgstr "|P|Введите код разблокировки PIN (PUK) Ð´Ð»Ñ ÑÑ
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr "|N|Введите новый PIN ключа Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ²Ð°Ð»Ð¸Ñ„Ð¸Ñ†Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ñ… подпиÑей."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr "||Введите PIN ключа Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ²Ð°Ð»Ð¸Ñ„Ð¸Ñ†Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ñ… подпиÑей."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6305,16 +6324,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr "%sÐомер: %s%%0AДержатель: %s%%0AСчетчик: %lu%s"
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr "%sÐомер: %s%%0AДержатель: %s%s"
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr "ОÑталоÑÑŒ попыток: %d"
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "оÑновной PIN применÑетÑÑ ÐºÐ°Ðº %s\n"
@@ -6567,6 +6576,10 @@ msgid "certificate policy not allowed"
msgstr "правила Ñертификата недопуÑтимы"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "Ñбой Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¾Ñ‚Ð¿ÐµÑ‡Ð°Ñ‚ÐºÐ°\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "внешний поиÑк издателÑ\n"
@@ -6575,6 +6588,10 @@ msgid "number of issuers matching: %d\n"
msgstr "чиÑло ÑоответÑтвующих издателей: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "не могу получить authorityInfoAccess: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "поиÑк Ð¸Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ Ð² буфере Dirmngr\n"
@@ -7158,10 +7175,6 @@ msgid "error reading input: %s\n"
msgstr "ошибка Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð²Ð²Ð¾Ð´Ð°: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "Ñбой Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¾Ñ‚Ð¿ÐµÑ‡Ð°Ñ‚ÐºÐ°\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "проблема поиÑка ÑущеÑтвующего Ñертификата: %s\n"
@@ -7253,9 +7266,10 @@ msgstr "ПодпиÑÑŒ Ñделана "
msgid "[date not given]"
msgstr "[дата не указана]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñертификата Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "алгоритм: %s"
#, c-format
msgid ""
@@ -7591,14 +7605,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… из файла буфера: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "недопуÑÑ‚Ð¸Ð¼Ð°Ñ Ñ…ÐµÑˆ-Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ '%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "Ñбой gcry_md_open Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° %d: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "из libksba получено недопуÑтимое S-выражение\n"
@@ -7607,6 +7613,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "Ñбой Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ S-выражениÑ: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "недопуÑÑ‚Ð¸Ð¼Ð°Ñ Ñ…ÐµÑˆ-Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ '%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "Ñбой gcry_md_open Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° %d: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "Ñбой ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ S-выражениÑ: %s\n"
@@ -8382,10 +8396,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "Ñбой при выделении памÑти под контекÑÑ‚ OCSP: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "не могу получить authorityInfoAccess: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "не определен оÑновной ответчик OCSP\n"
@@ -8962,6 +8972,9 @@ msgstr ""
"СинтакÑиÑ: gpg-check-pattern [параметры] файл_образцов\n"
"Проверить фразу-пароль, поÑтупающую из stdin, по файлу образцов\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñертификата Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ 0x%08lX\n"
+
#, fuzzy
#~| msgid "option '%s' may not be used in %s mode\n"
#~ msgid ""
diff --git a/po/sk.po b/po/sk.po
index 045c745..768f796 100644
--- a/po/sk.po
+++ b/po/sk.po
@@ -96,6 +96,9 @@ msgstr ""
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3712,6 +3715,9 @@ msgstr "chyba: neplatný odtlaÄok\n"
msgid "subkey \"%s\" not found\n"
msgstr "kÄ¾ÃºÄ `%s' nebol nájdený: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Digest: "
@@ -6446,6 +6452,26 @@ msgid ""
"List, export, import Keybox data\n"
msgstr "Použitie: gpg [možnosti] [súbory] (-h pre pomoc)"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "zmeniť heslo"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6467,10 +6493,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "zmeniť heslo"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "zmeniť heslo"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "Prosím výberte dôvod na revokáciu:\n"
@@ -6481,9 +6503,6 @@ msgstr "Prosím výberte dôvod na revokáciu:\n"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6539,16 +6558,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr ""
@@ -6804,6 +6813,10 @@ msgstr "zapisujem tajný kÄ¾ÃºÄ do `%s'\n"
msgid "certificate policy not allowed"
msgstr "zapisujem tajný kÄ¾ÃºÄ do `%s'\n"
+#, fuzzy, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "nemôžem inicializovať databázu dôvery: %s\n"
+
#, c-format
msgid "looking up issuer at external location\n"
msgstr ""
@@ -6812,6 +6825,11 @@ msgstr ""
msgid "number of issuers matching: %d\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "%s: can't access: %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "%s: nemôžem pristupovať k: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr ""
@@ -7422,10 +7440,6 @@ msgstr "chyba pri vytváraní hesla: %s\n"
msgid "error reading input: %s\n"
msgstr "chyba pri Äítaní `%s': %s\n"
-#, fuzzy, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "nemôžem inicializovať databázu dôvery: %s\n"
-
#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr ""
@@ -7505,8 +7519,8 @@ msgid "[date not given]"
msgstr ""
#, fuzzy, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr "chyba pri vytváraní hesla: %s\n"
+msgid "algorithm:"
+msgstr "ASCII kódovanie: %s\n"
#, c-format
msgid ""
@@ -7836,15 +7850,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "chyba pri vytváraní hesla: %s\n"
#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "neplatný hashovací algoritmus `%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
-#, fuzzy, c-format
#| msgid "invalid response from agent\n"
msgid "got an invalid S-expression from libksba\n"
msgstr "neplatná reakcia od agenta\n"
@@ -7854,6 +7859,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "nemožno otvoriť súbor: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "neplatný hashovací algoritmus `%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
msgid "creating S-expression failed: %s\n"
msgstr "zmazanie bloku kľúÄa sa nepodarilo: %s\n"
@@ -8635,11 +8649,6 @@ msgstr "vytvoriÅ¥ revokaÄný certifikát"
msgid "failed to allocate OCSP context: %s\n"
msgstr "nemôžem inicializovať databázu dôvery: %s\n"
-#, fuzzy, c-format
-#| msgid "%s: can't access: %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "%s: nemôžem pristupovať k: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9234,6 +9243,10 @@ msgid ""
msgstr ""
#, fuzzy
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr "chyba pri vytváraní hesla: %s\n"
+
+#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
#~ "keyserver option \"honor-keyserver-url\" may not be used in Tor mode\n"
diff --git a/po/sv.po b/po/sv.po
index 8632420..053b871 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -125,6 +125,9 @@ msgstr "stämmer inte överens - försök igen"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (försök %d av %d)"
@@ -3833,6 +3836,9 @@ msgstr "ogiltigt fingeravtryck"
msgid "subkey \"%s\" not found\n"
msgstr "nyckeln \"%s\" hittades inte: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Sammandrag: "
@@ -6678,6 +6684,25 @@ msgstr ""
"Syntax: kbxutil [flaggor] [filer]\n"
"lista, exportera, importera nyckelskåpsdata\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr "||Ange PIN-koden för nyckeln att skapa kvalificerade signaturer med."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Ange PIN-koden för standardnycklarna."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "RSA modulus saknas eller är inte %d bitar stor\n"
@@ -6697,9 +6722,6 @@ msgstr "NullPIN har ännu inte ändrats\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Ange en ny PIN-kod för standardnycklarna."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Ange PIN-koden för standardnycklarna."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "|NP|Ange en ny upplåsningskod (PUK-kod) för standardnycklarna."
@@ -6710,9 +6732,6 @@ msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
"|N|Ange en ny PIN-kod för nyckeln att skapa kvalificerade signaturer med."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr "||Ange PIN-koden för nyckeln att skapa kvalificerade signaturer med."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6772,16 +6791,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "använder standard-PIN som %s\n"
@@ -7054,6 +7063,10 @@ msgid "certificate policy not allowed"
msgstr "certifikatpolicy tillåts inte"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "misslyckades med att få fingeravtrycket\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "slår upp utfärdare på extern plats\n"
@@ -7061,6 +7074,11 @@ msgstr "slår upp utfärdare på extern plats\n"
msgid "number of issuers matching: %d\n"
msgstr "antal utfärdare som matchar: %d\n"
+#, fuzzy, c-format
+#| msgid "can't access `%s': %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "kan inte komma åt \"%s\": %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "slår upp utfärdare från Dirmngr-cachen\n"
@@ -7687,10 +7705,6 @@ msgid "error reading input: %s\n"
msgstr "fel vid läsning av indata: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "misslyckades med att få fingeravtrycket\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "problem vid sökandet efter befintligt certifikat: %s\n"
@@ -7783,9 +7797,10 @@ msgstr "Signatur gjord "
msgid "[date not given]"
msgstr "[datum inte angivet]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " använder certifikat-id 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "algoritm: %s"
#, c-format
msgid ""
@@ -8157,15 +8172,6 @@ msgstr ""
msgid "error getting data from cache file: %s\n"
msgstr "fel vid hämtning av lagrade flaggor: %s\n"
-#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "ogiltig kontrollsummealgoritm \"%s\"\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr ""
@@ -8176,6 +8182,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "iconv_open misslyckades: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "ogiltig kontrollsummealgoritm \"%s\"\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
#| msgid "receiving line failed: %s\n"
msgid "creating S-expression failed: %s\n"
msgstr "mottagande rad misslyckades: %s\n"
@@ -9058,11 +9073,6 @@ msgstr "fel vid lagring av certifikat\n"
msgid "failed to allocate OCSP context: %s\n"
msgstr "misslyckades med att allokera keyDB-hanterare\n"
-#, fuzzy, c-format
-#| msgid "can't access `%s': %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "kan inte komma åt \"%s\": %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9704,6 +9714,9 @@ msgstr ""
"Syntax: gpg-check-pattern [flaggor] mönsterfil\n"
"Kontrollera en lösenfras angiven på standard in mot mönsterfilen\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " använder certifikat-id 0x%08lX\n"
+
#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
diff --git a/po/tr.po b/po/tr.po
index 50e9feb..03b225a 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -99,6 +99,9 @@ msgstr "aynı değiller - tekrar deneyin"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (%d/%d dene)"
@@ -3776,6 +3779,9 @@ msgstr "parmakizi geçersiz"
msgid "subkey \"%s\" not found\n"
msgstr "anahtar \"%s\" yok: %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Özet: "
@@ -6588,6 +6594,26 @@ msgstr ""
"Sözdizimi: kbxutil [seçenekler] [dosyalar]\n"
"Anahtar kutusu verisini listeler, ithal ve ihraç eder\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+
+#, fuzzy
+msgid "||Please enter the PIN for the standard keys."
+msgstr "|A|Lütfen Yönetici PIN'ini okuyucu tuştakımından giriniz"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "RSA modülü ya eksik ya da %d bitlik değil\n"
@@ -6609,10 +6635,6 @@ msgid "|N|Please enter a new PIN for the standard keys."
msgstr "||Lütfen PIN'inizi okuyucunun tuştakımından giriniz"
#, fuzzy
-msgid "||Please enter the PIN for the standard keys."
-msgstr "|A|Lütfen Yönetici PIN'ini okuyucu tuştakımından giriniz"
-
-#, fuzzy
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "||Lütfen kart için Sıfırlama Kodunu giriniz"
@@ -6623,9 +6645,6 @@ msgstr "||Lütfen kart için Sıfırlama Kodunu giriniz"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr ""
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6681,16 +6700,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "%s olarak öntanımlı PIN kullanılıyor\n"
@@ -6964,6 +6973,10 @@ msgid "certificate policy not allowed"
msgstr "sertifika poliçesine izin verilmiyor"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "parmakizinin alınması başarısız oldu\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "harici bir sertifikacı arar\n"
@@ -6971,6 +6984,11 @@ msgstr "harici bir sertifikacı arar\n"
msgid "number of issuers matching: %d\n"
msgstr "eşleşen sertifikacı sayısı: %d\n"
+#, fuzzy, c-format
+#| msgid "can't access `%s': %s\n"
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "'%s' eriÅŸilemiyor: %s\n"
+
#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "Dirmngr önbelleğinde sertifikacıyı arar\n"
@@ -7595,10 +7613,6 @@ msgid "error reading input: %s\n"
msgstr "girdi okunurken hata: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "parmakizinin alınması başarısız oldu\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "mevcut sertifika aranırken sorun çıktı: %s\n"
@@ -7689,9 +7703,10 @@ msgstr "Ä°mza "
msgid "[date not given]"
msgstr "[belirtilmeyen tarihte]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " sertifika kimliği 0x%08lX kullanılarak yapıldı\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "algoritma: %s"
#, c-format
msgid ""
@@ -8062,15 +8077,6 @@ msgstr ""
msgid "error getting data from cache file: %s\n"
msgstr "saklanmış bayraklar alınırken hata: %s\n"
-#, fuzzy, c-format
-#| msgid "invalid hash algorithm `%s'\n"
-msgid "unknown hash algorithm '%s'\n"
-msgstr "`%s' çittirim algoritması geçersiz\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr ""
-
#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr ""
@@ -8081,6 +8087,15 @@ msgid "converting S-expression failed: %s\n"
msgstr "iconv_open başarısız: %s\n"
#, fuzzy, c-format
+#| msgid "invalid hash algorithm `%s'\n"
+msgid "unknown hash algorithm '%s'\n"
+msgstr "`%s' çittirim algoritması geçersiz\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr ""
+
+#, fuzzy, c-format
#| msgid "receiving line failed: %s\n"
msgid "creating S-expression failed: %s\n"
msgstr "satır alımı başarısız: %s\n"
@@ -8958,11 +8973,6 @@ msgstr "sertifika saklanırken hata\n"
msgid "failed to allocate OCSP context: %s\n"
msgstr "anahtar veritabanı eylemcisine yer ayrılması başarısız oldu\n"
-#, fuzzy, c-format
-#| msgid "can't access `%s': %s\n"
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "'%s' eriÅŸilemiyor: %s\n"
-
#, c-format
msgid "no default OCSP responder defined\n"
msgstr ""
@@ -9606,6 +9616,9 @@ msgstr ""
"Standart girdiden verilen anahtar parolasını örüntü dosyasıyla "
"karşılaştırır\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " sertifika kimliği 0x%08lX kullanılarak yapıldı\n"
+
#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
diff --git a/po/uk.po b/po/uk.po
index 7586c9b..232fe6c 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -98,6 +98,9 @@ msgstr "паролі не збігаютьÑÑ, повторіть Ñпробу"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (Ñпроба %d з %d)"
@@ -3563,6 +3566,9 @@ msgstr "«%s» не є відбитком\n"
msgid "subkey \"%s\" not found\n"
msgstr "ключ «%s» не знайдено\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "Контрольна Ñума: "
@@ -6333,6 +6339,27 @@ msgstr ""
"СинтакÑиÑ: kbxutil [параметри] [файли]\n"
"ПереглÑд, екÑпортуваннÑ, Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… Keybox\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr ""
+"||Будь лаÑка, вкажіть пінкод Ð´Ð»Ñ ÐºÐ»ÑŽÑ‡Ð°, призначеного Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑкіÑних "
+"підпиÑів."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||Вкажіть пінкод Ð´Ð»Ñ Ñтандартних ключів."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr ""
@@ -6356,9 +6383,6 @@ msgstr "NullPIN ще не було змінено\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|Вкажіть новий пінкод Ð´Ð»Ñ Ñтандартних ключів."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||Вкажіть пінкод Ð´Ð»Ñ Ñтандартних ключів."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr ""
"|NP|Будь лаÑка, вкажіть новий код Ñ€Ð¾Ð·Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–Ð½ÐºÐ¾Ð´Ñƒ (PUK) Ð´Ð»Ñ "
@@ -6374,11 +6398,6 @@ msgstr ""
"|N|Будь лаÑка, вкажіть новий пінкод Ð´Ð»Ñ ÐºÐ»ÑŽÑ‡Ð°, призначеного Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ "
"ÑкіÑних підпиÑів."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr ""
-"||Будь лаÑка, вкажіть пінкод Ð´Ð»Ñ ÐºÐ»ÑŽÑ‡Ð°, призначеного Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑкіÑних "
-"підпиÑів."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6437,16 +6456,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "викориÑтовуємо типовий пінкод Ñк %s\n"
@@ -6705,6 +6714,10 @@ msgid "certificate policy not allowed"
msgstr "заборонено правила Ñертифікації"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ відбиток\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "пошук Ð²Ð¸Ð´Ð°Ð²Ñ†Ñ Ð·Ð° зовнішньою адреÑою\n"
@@ -6713,6 +6726,10 @@ msgid "number of issuers matching: %d\n"
msgstr "кількіÑÑ‚ÑŒ відповідних видавців: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ authorityInfoAccess: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "пошук Ð²Ð¸Ð´Ð°Ð²Ñ†Ñ Ñƒ кеші dirmngr\n"
@@ -7304,10 +7321,6 @@ msgid "error reading input: %s\n"
msgstr "помилка під Ñ‡Ð°Ñ Ñпроби Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð²Ñ…Ñ–Ð´Ð½Ð¸Ñ… даних: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ відбиток\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "проблем з пошуком вже Ñтвореного Ñертифіката: %s\n"
@@ -7398,9 +7411,10 @@ msgstr "ÐŸÑ–Ð´Ð¿Ð¸Ñ Ñтворено "
msgid "[date not given]"
msgstr "[дату не вказано]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " викориÑтовуємо ідентифікатор Ñертифіката 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "алгоритм: %s"
#, c-format
msgid ""
@@ -7731,14 +7745,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "помилка під Ñ‡Ð°Ñ Ñпроби Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… з файла кешу: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "невідомий алгоритм Ñ…ÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Â«%s»\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "помилка викориÑÑ‚Ð°Ð½Ð½Ñ gcry_md_open Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ñƒ %d: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "отримано некоректний вираз S з libksba\n"
@@ -7747,6 +7753,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "Ñпроба Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð¸Ñ€Ð°Ð·Ñƒ S зазнала невдачі: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "невідомий алгоритм Ñ…ÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Â«%s»\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "помилка викориÑÑ‚Ð°Ð½Ð½Ñ gcry_md_open Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ñƒ %d: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "Ñпроба ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð¸Ñ€Ð°Ð·Ñƒ S зазнала невдачі: %s\n"
@@ -8509,10 +8523,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¼Ñ–Ñтити контекÑÑ‚ OCSP: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ authorityInfoAccess: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "не визначено типового відповідача за OCSP\n"
@@ -9091,6 +9101,9 @@ msgstr ""
"СинтакÑиÑ: gpg-check-pattern [параметри] файл_шаблонів\n"
"Перевірити пароль, вказаний у stdin, за допомогою файла_шаблонів\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " викориÑтовуємо ідентифікатор Ñертифіката 0x%08lX\n"
+
#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
diff --git a/po/zh_CN.po b/po/zh_CN.po
index a46ad1b..48f2ea7 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -93,6 +93,9 @@ msgstr "ä¸åŒ¹é… - 请é‡è¯•"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr ""
@@ -3418,6 +3421,9 @@ msgstr "“%s†ä¸æ˜¯ä¸€ä¸ªæ­£ç¡®çš„指纹\n"
msgid "subkey \"%s\" not found\n"
msgstr "å­å¯†é’¥ “%s†未找到\n"
+msgid "AEAD: "
+msgstr "AEAD: "
+
msgid "Digest: "
msgstr "摘è¦ï¼š "
@@ -5969,6 +5975,25 @@ msgstr ""
"语法:kbxutil [选项] [文件]\n"
"列出ã€å¯¼å‡ºæˆ–导入钥匙箱数æ®\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr "%sæ•°å­—: %s%%0AæŒæœ‰è€…: %s%s"
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr "剩余å°è¯•ï¼š%d"
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr "||请为这个密钥输入 PIN 以创建åˆæ ¼çš„ç­¾å。"
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||请输入标准密钥的 PIN。"
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "RSA 余数缺失或者ä¸æ˜¯ %d ä½é•¿\n"
@@ -5988,9 +6013,6 @@ msgstr "尚未å˜æ›´ NullPIN\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|请为标准密钥输入一个新的 PIN。"
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||请输入标准密钥的 PIN。"
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "|NP|请为标准密钥输入一个新的 PIN 解é”ç ï¼ˆPUK)。"
@@ -6000,9 +6022,6 @@ msgstr "|NP|请输入标准密钥的 PIN 解é”ç ï¼ˆPUK)。"
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr "|N|请为这个密钥输入一个新的 PIN 以创建åˆæ ¼çš„ç­¾å。"
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr "||请为这个密钥输入 PIN 以创建åˆæ ¼çš„ç­¾å。"
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6057,16 +6076,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr "%sæ•°å­—: %s%%0AæŒæœ‰è€…: %s%%0A计数: %lu%s"
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr "%sæ•°å­—: %s%%0AæŒæœ‰è€…: %s%s"
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr "剩余å°è¯•ï¼š%d"
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "使用默认 PIN 作为 %s\n"
@@ -6308,6 +6317,10 @@ msgid "certificate policy not allowed"
msgstr "è¯ä¹¦ç­–ç•¥ä¸è¢«å…许"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "获å–指纹失败\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "在外部ä½ç½®æŸ¥æ‰¾ç­¾å‘者\n"
@@ -6316,6 +6329,10 @@ msgid "number of issuers matching: %d\n"
msgstr "匹é…çš„ç­¾å‘者数目:%d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "æ— æ³•èŽ·å– authorityInfoAccess:%s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "在 Dirmngr 缓存中查找签å‘者\n"
@@ -6892,10 +6909,6 @@ msgid "error reading input: %s\n"
msgstr "读å–输入时出现错误:%s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "获å–指纹失败\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "查找现存è¯ä¹¦æ—¶å‡ºçŽ°é—®é¢˜ï¼š%s\n"
@@ -6981,9 +6994,10 @@ msgstr "已签å "
msgid "[date not given]"
msgstr "[日期未指定]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " 正在使用的è¯ä¹¦æ ‡è¯† 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "算法: %s"
#, c-format
msgid ""
@@ -7312,14 +7326,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "从缓存文件中获å–æ•°æ®æ—¶å‡ºçŽ°é”™è¯¯ï¼š%s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "未知的散列算法‘%s’\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "算法 %d 的 gcry_md_open 方法失败:%s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "从 libksba 获得了无效的 S 表达å¼\n"
@@ -7328,6 +7334,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "è½¬æ¢ S 表达å¼æ—¶å¤±è´¥ï¼š%s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "未知的散列算法‘%s’\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "算法 %d 的 gcry_md_open 方法失败:%s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "创建 S 表达å¼æ—¶å¤±è´¥ï¼š%s\n"
@@ -8074,10 +8088,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "åˆ†é… OCSP 上下文时失败:%s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "æ— æ³•èŽ·å– authorityInfoAccess:%s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "未定义默认的 OCSP å“应者\n"
@@ -8652,6 +8662,9 @@ msgstr ""
"语法:gpg-check-pattern [选项] patternfile\n"
"按照 patternfile 检查一个由标准输入(stdin)给定的密ç \n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " 正在使用的è¯ä¹¦æ ‡è¯† 0x%08lX\n"
+
#, fuzzy
#~| msgid "option '%s' may not be used in %s mode\n"
#~ msgid ""
@@ -8733,9 +8746,6 @@ msgstr ""
#~ msgid " \"%s\": preference for AEAD algorithm %s\n"
#~ msgstr " \"%s\":关于 AEAD 算法 %s çš„å好设置\n"
-#~ msgid "AEAD: "
-#~ msgstr "AEAD: "
-
#~ msgid "too many AEAD preferences\n"
#~ msgstr "过多的 AEAD å好设置\n"
diff --git a/po/zh_TW.po b/po/zh_TW.po
index beb8bc1..50d7ca6 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -106,6 +106,9 @@ msgstr "å‰å¾Œä¸ä¸€è‡´ - è«‹å†è©¦ä¸€æ¬¡"
#. the pinentry. The %s is the actual error message, the
#. two %d give the current and maximum number of tries.
#. Do not translate the "SETERROR" keyword.
+#. TRANSLATORS: The string is appended to an error message in
+#. the pinentry. The %s is the actual error message, the
+#. two %d give the current and maximum number of tries.
#, c-format
msgid "SETERROR %s (try %d of %d)"
msgstr "SETERROR %s (第 %d 次嘗試, 最多 %d 次)"
@@ -3516,6 +3519,9 @@ msgstr "\"%s\" ä¸æ˜¯æŒ‡ç´‹\n"
msgid "subkey \"%s\" not found\n"
msgstr "找ä¸åˆ°é‡‘é‘° \"%s\": %s\n"
+msgid "AEAD: "
+msgstr ""
+
msgid "Digest: "
msgstr "摘è¦: "
@@ -6165,6 +6171,25 @@ msgstr ""
"語法: kbxutil [é¸é …] [檔案]\n"
"列出, 匯出, 匯入金鑰鑰匙盒資料\n"
+#. TRANSLATORS: Put a \x1f right before a colon. This can be
+#. * used by pinentry to nicely align the names and values. Keep
+#. * the %s at the start and end of the string.
+#, c-format
+msgid "%sNumber: %s%%0AHolder: %s%s"
+msgstr ""
+
+#. TRANSLATORS: This is the number of remaining attempts to
+#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
+#, c-format
+msgid "Remaining attempts: %d"
+msgstr ""
+
+msgid "||Please enter the PIN for the key to create qualified signatures."
+msgstr "||請輸入金鑰的個人識別碼 (PIN) 以建立完善的簽章."
+
+msgid "||Please enter the PIN for the standard keys."
+msgstr "||請輸入標準金鑰的個人識別碼 (PIN)."
+
#, c-format
msgid "RSA modulus missing or not of size %d bits\n"
msgstr "RSA 模組缺æ¼æˆ–è€…ä¸¦éž %d ä½å…ƒå¤§\n"
@@ -6184,9 +6209,6 @@ msgstr "NullPIN 還沒有變更éŽ\n"
msgid "|N|Please enter a new PIN for the standard keys."
msgstr "|N|請輸入標準金鑰將採用的新個人識別碼 (PIN)."
-msgid "||Please enter the PIN for the standard keys."
-msgstr "||請輸入標準金鑰的個人識別碼 (PIN)."
-
msgid "|NP|Please enter a new PIN Unblocking Code (PUK) for the standard keys."
msgstr "|NP|請輸入標準金鑰將採用的 PIN é‡è¨­ç¢¼ (PUK)."
@@ -6196,9 +6218,6 @@ msgstr "|P|請輸入標準金鑰的 PIN é‡è¨­ç¢¼ (PUK)."
msgid "|N|Please enter a new PIN for the key to create qualified signatures."
msgstr "|N|請輸入金鑰的新個人識別碼 (PIN) 以建立完善的簽章."
-msgid "||Please enter the PIN for the key to create qualified signatures."
-msgstr "||請輸入金鑰的個人識別碼 (PIN) 以建立完善的簽章."
-
msgid ""
"|NP|Please enter a new PIN Unblocking Code (PUK) for the key to create "
"qualified signatures."
@@ -6254,16 +6273,6 @@ msgid "%sNumber: %s%%0AHolder: %s%%0ACounter: %lu%s"
msgstr ""
#, c-format
-msgid "%sNumber: %s%%0AHolder: %s%s"
-msgstr ""
-
-#. TRANSLATORS: This is the number of remaining attempts to
-#. * enter a PIN. Use %%0A (double-percent,0A) for a linefeed.
-#, c-format
-msgid "Remaining attempts: %d"
-msgstr ""
-
-#, c-format
msgid "using default PIN as %s\n"
msgstr "以 %s åšç‚ºé è¨­ PIN\n"
@@ -6510,6 +6519,10 @@ msgid "certificate policy not allowed"
msgstr "未å…許憑證原則"
#, c-format
+msgid "failed to get the fingerprint\n"
+msgstr "å–得指紋失敗\n"
+
+#, c-format
msgid "looking up issuer at external location\n"
msgstr "從外部ä½ç½®å°‹æ‰¾ç™¼è¡Œè€…\n"
@@ -6518,6 +6531,10 @@ msgid "number of issuers matching: %d\n"
msgstr "å»åˆçš„發行者數é‡: %d\n"
#, c-format
+msgid "can't get authorityInfoAccess: %s\n"
+msgstr "無法å–å¾— authorityInfoAccess: %s\n"
+
+#, c-format
msgid "looking up issuer from the Dirmngr cache\n"
msgstr "從 Dirmngr å¿«å–尋找發行者\n"
@@ -7094,10 +7111,6 @@ msgid "error reading input: %s\n"
msgstr "讀å–輸入時出錯: %s\n"
#, c-format
-msgid "failed to get the fingerprint\n"
-msgstr "å–得指紋失敗\n"
-
-#, c-format
msgid "problem looking for existing certificate: %s\n"
msgstr "查找既有憑證的å•é¡Œ: %s\n"
@@ -7183,9 +7196,10 @@ msgstr "簽章建立於 "
msgid "[date not given]"
msgstr "[ 未給定日期 ]"
-#, c-format
-msgid " using certificate ID 0x%08lX\n"
-msgstr " 以憑證 ID 0x%08lX\n"
+#, fuzzy, c-format
+#| msgid "algorithm: %s"
+msgid "algorithm:"
+msgstr "演算法: %s"
#, c-format
msgid ""
@@ -7506,14 +7520,6 @@ msgid "error getting data from cache file: %s\n"
msgstr "從快å–檔案å–得資料時出錯: %s\n"
#, c-format
-msgid "unknown hash algorithm '%s'\n"
-msgstr "未知的雜湊演算法 '%s'\n"
-
-#, c-format
-msgid "gcry_md_open for algorithm %d failed: %s\n"
-msgstr "演算法 %d 的 gcry_md_open 失敗: %s\n"
-
-#, c-format
msgid "got an invalid S-expression from libksba\n"
msgstr "從 libksba 得到無效的 S-表示å¼\n"
@@ -7522,6 +7528,14 @@ msgid "converting S-expression failed: %s\n"
msgstr "è½‰æ› S-表示å¼æ™‚失敗: %s\n"
#, c-format
+msgid "unknown hash algorithm '%s'\n"
+msgstr "未知的雜湊演算法 '%s'\n"
+
+#, c-format
+msgid "gcry_md_open for algorithm %d failed: %s\n"
+msgstr "演算法 %d 的 gcry_md_open 失敗: %s\n"
+
+#, c-format
msgid "creating S-expression failed: %s\n"
msgstr "建立 S-表示å¼æ™‚失敗: %s\n"
@@ -8270,10 +8284,6 @@ msgid "failed to allocate OCSP context: %s\n"
msgstr "é…ç½® OCSP 脈絡失敗: %s\n"
#, c-format
-msgid "can't get authorityInfoAccess: %s\n"
-msgstr "無法å–å¾— authorityInfoAccess: %s\n"
-
-#, c-format
msgid "no default OCSP responder defined\n"
msgstr "無定義é è¨­ OCSP 回應程å¼\n"
@@ -8865,6 +8875,9 @@ msgstr ""
"語法: gpg-check-pattern [é¸é …] 樣å¼æª”案\n"
"用樣å¼æª”案來檢查由標準輸入給定的密語\n"
+#~ msgid " using certificate ID 0x%08lX\n"
+#~ msgstr " 以憑證 ID 0x%08lX\n"
+
#, fuzzy
#~| msgid "you may not use %s while in %s mode\n"
#~ msgid ""
diff --git a/scd/apdu.c b/scd/apdu.c
index 274f2db..dfd9451 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -475,7 +475,7 @@ dump_reader_status (int slot)
if (reader_table[slot].atrlen)
{
log_info ("slot %d: ATR=", slot);
- log_printhex ("", reader_table[slot].atr, reader_table[slot].atrlen);
+ log_printhex (reader_table[slot].atr, reader_table[slot].atrlen, "");
}
}
@@ -739,7 +739,7 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
return err;
if (DBG_CARD_IO)
- log_printhex (" PCSC_data:", apdu, apdulen);
+ log_printhex (apdu, apdulen, " PCSC_data:");
if ((reader_table[slot].pcsc.protocol & PCSC_PROTOCOL_T1))
send_pci.protocol = PCSC_PROTOCOL_T1;
@@ -1453,7 +1453,7 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
return err;
if (DBG_CARD_IO)
- log_printhex (" raw apdu:", apdu, apdulen);
+ log_printhex (apdu, apdulen, " raw apdu:");
maxbuflen = *buflen;
if (pininfo)
@@ -1723,7 +1723,7 @@ my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
*buflen = 0;
if (DBG_CARD_IO)
- log_printhex (" APDU_data:", apdu, apdulen);
+ log_printhex (apdu, apdulen, " APDU_data:");
if (apdulen < 4)
{
@@ -2879,7 +2879,7 @@ send_le (int slot, int class, int ins, int p0, int p1,
log_debug (" response: sw=%04X datalen=%d\n",
sw, (unsigned int)resultlen);
if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA))
- log_printhex (" dump: ", result, resultlen);
+ log_printhex (result, resultlen, " dump: ");
}
if (sw == SW_SUCCESS || sw == SW_EOF_REACHED)
@@ -2952,7 +2952,7 @@ send_le (int slot, int class, int ins, int p0, int p1,
log_debug (" more: sw=%04X datalen=%d\n",
sw, (unsigned int)resultlen);
if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA))
- log_printhex (" dump: ", result, resultlen);
+ log_printhex (result, resultlen, " dump: ");
}
if ((sw & 0xff00) == SW_MORE_DATA
@@ -2998,7 +2998,7 @@ send_le (int slot, int class, int ins, int p0, int p1,
xfree (result_buffer);
if (DBG_CARD_IO && retbuf && sw == SW_SUCCESS)
- log_printhex (" dump: ", *retbuf, *retbuflen);
+ log_printhex (*retbuf, *retbuflen, " dump: ");
return sw;
}
@@ -3164,7 +3164,7 @@ apdu_send_direct (int slot, size_t extended_length,
log_debug (" response: sw=%04X datalen=%d\n",
sw, (unsigned int)resultlen);
if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA))
- log_printhex (" dump: ", result, resultlen);
+ log_printhex (result, resultlen, " dump: ");
}
if (handle_more && (sw & 0xff00) == SW_MORE_DATA)
@@ -3220,7 +3220,7 @@ apdu_send_direct (int slot, size_t extended_length,
log_debug (" more: sw=%04X datalen=%d\n",
sw, (unsigned int)resultlen);
if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA))
- log_printhex (" dump: ", result, resultlen);
+ log_printhex (result, resultlen, " dump: ");
}
if ((sw & 0xff00) == SW_MORE_DATA
@@ -3292,7 +3292,7 @@ apdu_send_direct (int slot, size_t extended_length,
*r_sw = sw;
if (DBG_CARD_IO && retbuf)
- log_printhex (" dump: ", *retbuf, *retbuflen);
+ log_printhex (*retbuf, *retbuflen, " dump: ");
return 0;
diff --git a/scd/app-common.h b/scd/app-common.h
index 2619823..89467dc 100644
--- a/scd/app-common.h
+++ b/scd/app-common.h
@@ -119,9 +119,26 @@ struct app_ctx_s {
} fnc;
};
+
+/* Helper to get the slot from an APP object. */
+static inline int
+app_get_slot (app_t app)
+{
+ /* Note that this is a similar function of the one in 2.3 which we
+ * use to make back porting easier. */
+ if (app)
+ return app->slot;
+ return -1;
+}
+
+
/*-- app-help.c --*/
unsigned int app_help_count_bits (const unsigned char *a, size_t len);
-gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip);
+gpg_error_t app_help_get_keygrip_string_pk (const void *pk, size_t pklen,
+ char *hexkeygrip,
+ gcry_sexp_t *r_pkey);
+gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip,
+ gcry_sexp_t *r_pkey);
size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff);
diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c
index bea2856..b0c47af 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -137,7 +137,7 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
ksba_cert_release (cert);
return err;
}
- err = app_help_get_keygrip_string (cert, hexkeygrip);
+ err = app_help_get_keygrip_string (cert, hexkeygrip, NULL);
if (err)
{
log_error ("failed to calculate the keygrip for FID 0x%04X\n", fid);
diff --git a/scd/app-help.c b/scd/app-help.c
index 842a73d..4b8a024 100644
--- a/scd/app-help.c
+++ b/scd/app-help.c
@@ -52,26 +52,24 @@ app_help_count_bits (const unsigned char *a, size_t len)
}
-/* Return the KEYGRIP for the certificate CERT as an hex encoded
- string in the user provided buffer HEXKEYGRIP which must be of at
- least 41 bytes. */
+/* Return the KEYGRIP for the canonical encoded public key (PK,PKLEN)
+ * as an hex encoded string in the user provided buffer HEXKEYGRIP
+ * which must be of at least 41 bytes. If R_PKEY is not NULL and the
+ * function succeeded, the S-expression representing the key is
+ * stored there. The caller needs to call gcry_sexp_release on
+ * that. */
gpg_error_t
-app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip)
+app_help_get_keygrip_string_pk (const void *pk, size_t pklen, char *hexkeygrip,
+ gcry_sexp_t *r_pkey)
{
gpg_error_t err;
gcry_sexp_t s_pkey;
- ksba_sexp_t p;
- size_t n;
- unsigned char array[20];
+ unsigned char array[KEYGRIP_LEN];
- p = ksba_cert_get_public_key (cert);
- if (!p)
- return gpg_error (GPG_ERR_BUG);
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- err = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
- xfree (p);
+ if (r_pkey)
+ *r_pkey = NULL;
+
+ err = gcry_sexp_sscan (&s_pkey, NULL, pk, pklen);
if (err)
return err; /* Can't parse that S-expression. */
if (!gcry_pk_get_keygrip (s_pkey, array))
@@ -79,14 +77,45 @@ app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip)
gcry_sexp_release (s_pkey);
return gpg_error (GPG_ERR_GENERAL); /* Failed to calculate the keygrip.*/
}
- gcry_sexp_release (s_pkey);
- bin2hex (array, 20, hexkeygrip);
+ if (r_pkey)
+ *r_pkey = s_pkey;
+ else
+ gcry_sexp_release (s_pkey);
+
+ bin2hex (array, KEYGRIP_LEN, hexkeygrip);
return 0;
}
+/* Return the KEYGRIP for the certificate CERT as an hex encoded
+ * string in the user provided buffer HEXKEYGRIP which must be of at
+ * least 41 bytes. If R_PKEY is not NULL and the function succeeded,
+ * the S-expression representing the key is stored there. The caller
+ * needs to call gcry_sexp_release on that. */
+gpg_error_t
+app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip,
+ gcry_sexp_t *r_pkey)
+{
+ gpg_error_t err;
+ ksba_sexp_t p;
+ size_t n;
+
+ if (r_pkey)
+ *r_pkey = NULL;
+
+ p = ksba_cert_get_public_key (cert);
+ if (!p)
+ return gpg_error (GPG_ERR_BUG);
+ n = gcry_sexp_canon_len (p, 0, NULL, NULL);
+ if (!n)
+ return gpg_error (GPG_ERR_INV_SEXP);
+ err = app_help_get_keygrip_string_pk ((void*)p, n, hexkeygrip, r_pkey);
+ ksba_free (p);
+ return err;
+}
+
/* Given the SLOT and the File ID FID, return the length of the
certificate contained in that file. Returns 0 if the file does not
diff --git a/scd/app-nks.c b/scd/app-nks.c
index 9371932..58a5349 100644
--- a/scd/app-nks.c
+++ b/scd/app-nks.c
@@ -248,53 +248,17 @@ keygripstr_from_pk_file (app_t app, int fid, char *r_gripstr)
/* TCOS responds to a verify with empty data (i.e. without the Lc
- byte) with the status of the PIN. PWID is the PIN ID, If SIGG is
- true, the application is switched into SigG mode.
- Returns:
- -1 = Error retrieving the data,
- -2 = No such PIN,
- -3 = PIN blocked,
- -4 = NullPIN activ,
- n >= 0 = Number of verification attempts left. */
+ * byte) with the status of the PIN. PWID is the PIN ID, If SIGG is
+ * true, the application is switched into SigG mode. Returns:
+ * ISO7816_VERIFY_* codes or non-negative number of verification
+ * attempts left. */
static int
get_chv_status (app_t app, int sigg, int pwid)
{
- unsigned char *result = NULL;
- size_t resultlen;
- char command[4];
- int rc;
-
if (switch_application (app, sigg))
return sigg? -2 : -1; /* No such PIN / General error. */
- command[0] = 0x00;
- command[1] = 0x20;
- command[2] = 0x00;
- command[3] = pwid;
-
- if (apdu_send_direct (app->slot, 0, (unsigned char *)command,
- 4, 0, NULL, &result, &resultlen))
- rc = -1; /* Error. */
- else if (resultlen < 2)
- rc = -1; /* Error. */
- else
- {
- unsigned int sw = buf16_to_uint (result+resultlen-2);
-
- if (sw == 0x6a88)
- rc = -2; /* No such PIN. */
- else if (sw == 0x6983)
- rc = -3; /* PIN is blocked. */
- else if (sw == 0x6985)
- rc = -4; /* NullPIN is activ. */
- else if ((sw & 0xfff0) == 0x63C0)
- rc = (sw & 0x000f); /* PIN has N tries left. */
- else
- rc = -1; /* Other error. */
- }
- xfree (result);
-
- return rc;
+ return iso7816_verify_status (app_get_slot (app), pwid);
}
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index fe13f28..7fc903b 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -268,6 +268,47 @@ static gpg_error_t change_keyattr_from_string
void *pincb_arg,
const void *value, size_t valuelen);
+
+/* Return the OpenPGP card manufacturer name. */
+static const char *
+get_manufacturer (unsigned int no)
+{
+ /* Note: Make sure that there is no colon or linefeed in the string. */
+ switch (no)
+ {
+ case 0x0001: return "PPC Card Systems";
+ case 0x0002: return "Prism";
+ case 0x0003: return "OpenFortress";
+ case 0x0004: return "Wewid";
+ case 0x0005: return "ZeitControl";
+ case 0x0006: return "Yubico";
+ case 0x0007: return "OpenKMS";
+ case 0x0008: return "LogoEmail";
+ case 0x0009: return "Fidesmo";
+ case 0x000A: return "Dangerous Things";
+ case 0x000B: return "Feitian Technologies";
+
+ case 0x002A: return "Magrathea";
+ case 0x0042: return "GnuPG e.V.";
+
+ case 0x1337: return "Warsaw Hackerspace";
+ case 0x2342: return "warpzone"; /* hackerspace Muenster. */
+ case 0x4354: return "Confidential Technologies"; /* cotech.de */
+ case 0x5443: return "TIF-IT e.V.";
+ case 0x63AF: return "Trustica";
+ case 0xBA53: return "c-base e.V.";
+ case 0xBD0E: return "Paranoidlabs";
+ case 0xF517: return "FSIJ";
+ case 0xF5EC: return "F-Secure";
+
+ /* 0x0000 and 0xFFFF are defined as test cards per spec,
+ * 0xFF00 to 0xFFFE are assigned for use with randomly created
+ * serial numbers. */
+ case 0x0000:
+ case 0xffff: return "test card";
+ default: return (no & 0xff00) == 0xff00? "unmanaged S/N range":"unknown";
+ }
+}
@@ -567,7 +608,7 @@ dump_all_do (int slot)
if (data_objects[i].binary)
{
log_info ("DO '%s': ", data_objects[i].desc);
- log_printhex ("", buffer, buflen);
+ log_printhex (buffer, buflen, "");
}
else
log_info ("DO '%s': '%.*s'\n",
@@ -597,7 +638,7 @@ dump_all_do (int slot)
if (valuelen > 200)
log_info ("[%u]\n", (unsigned int)valuelen);
else
- log_printhex ("", value, valuelen);
+ log_printhex (value, valuelen, "");
}
else
log_info ("DO '%s': '%.*s'\n",
@@ -992,6 +1033,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
{ "$SIGNKEYID", 0x0000, -7 },
{ "$DISPSERIALNO",0x0000, -4 },
{ "KDF", 0x00F9, 5 },
+ { "MANUFACTURER", 0x0000, -8 },
{ NULL, 0 }
};
int idx, i, rc;
@@ -1083,6 +1125,13 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
return 0;
}
+ if (table[idx].special == -8)
+ {
+ return send_status_printf
+ (ctrl, table[idx].name, "%u %s",
+ app->app_local->manufacturer,
+ get_manufacturer (app->app_local->manufacturer));
+ }
relptr = get_one_do (app, table[idx].tag, &value, &valuelen, &rc);
if (relptr)
@@ -1860,6 +1909,7 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
(void)flags;
do_getattr (app, ctrl, "EXTCAP");
+ do_getattr (app, ctrl, "MANUFACTURER");
do_getattr (app, ctrl, "DISP-NAME");
do_getattr (app, ctrl, "DISP-LANG");
do_getattr (app, ctrl, "DISP-SEX");
@@ -4239,7 +4289,7 @@ compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr)
return gpg_error (GPG_ERR_GENERAL);
}
fpr = find_tlv (buffer, buflen, 0x00C5, &n);
- if (!fpr || n != 60)
+ if (!fpr || n < 60)
{
xfree (buffer);
log_error (_("error reading fingerprint DO\n"));
@@ -5156,7 +5206,7 @@ parse_algorithm_attribute (app_t app, int keyno)
curve = ecc_curve (buffer + 1, oidlen);
if (!curve)
- log_printhex ("Curve with OID not supported: ", buffer+1, buflen-1);
+ log_printhex (buffer+1, buflen-1, "Curve with OID not supported: ");
else
{
app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECC;
@@ -5174,7 +5224,7 @@ parse_algorithm_attribute (app_t app, int keyno)
}
}
else if (opt.verbose)
- log_printhex ("", buffer, buflen);
+ log_printhex (buffer, buflen, "");
xfree (relptr);
}
@@ -5216,7 +5266,7 @@ app_select_openpgp (app_t app)
if (opt.verbose)
{
log_info ("AID: ");
- log_printhex ("", buffer, buflen);
+ log_printhex (buffer, buflen, "");
}
app->card_version = buffer[6] << 8;
@@ -5249,7 +5299,7 @@ app_select_openpgp (app_t app)
if (opt.verbose)
{
log_info ("Historical Bytes: ");
- log_printhex ("", buffer, buflen);
+ log_printhex (buffer, buflen, "");
}
parse_historical (app->app_local, buffer, buflen);
xfree (relptr);
diff --git a/scd/app-p15.c b/scd/app-p15.c
index 0bb5f9e..9ad0d16 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -1,5 +1,6 @@
/* app-p15.c - The pkcs#15 card application.
* Copyright (C) 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2020 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -15,6 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
/* Information pertaining to the BELPIC developer card samples:
@@ -39,6 +41,7 @@
#include "iso7816.h"
#include "app-common.h"
+#include "../common/i18n.h"
#include "../common/tlv.h"
#include "apdu.h" /* fixme: we should move the card detection to a
separate file */
@@ -49,10 +52,22 @@ typedef enum
CARD_TYPE_UNKNOWN,
CARD_TYPE_TCOS,
CARD_TYPE_MICARDO,
+ CARD_TYPE_CARDOS_50,
CARD_TYPE_BELPIC /* Belgian eID card specs. */
}
card_type_t;
+/* The OS of card as specified by card_type_t is not always
+ * sufficient. Thus we also distinguish the actual product build upon
+ * the given OS. */
+typedef enum
+ {
+ CARD_PRODUCT_UNKNOWN,
+ CARD_PRODUCT_DTRUST /* D-Trust GmbH (bundesdruckerei.de) */
+ }
+card_product_t;
+
+
/* A list card types with ATRs noticed with these cards. */
#define X(a) ((unsigned char const *)(a))
static struct
@@ -79,7 +94,8 @@ static struct
{ 26, X("\x3B\xFE\x94\x00\xFF\x80\xB1\xFA\x45\x1F\x03\x45\x73\x74\x45\x49"
"\x44\x20\x76\x65\x72\x20\x31\x2E\x30\x43"),
CARD_TYPE_MICARDO }, /* EstEID (Estonian Big Brother card) */
-
+ { 11, X("\x3b\xd2\x18\x00\x81\x31\xfe\x58\xc9\x01\x14"),
+ CARD_TYPE_CARDOS_50 }, /* CardOS 5.0 */
{ 0 }
};
#undef X
@@ -135,7 +151,12 @@ struct cdf_object_s
/* Link to next item when used in a linked list. */
struct cdf_object_s *next;
- /* Length and allocated buffer with the Id of this object. */
+ /* Flags to indicate whether fields are valid. */
+ unsigned int have_off:1;
+
+ /* Length and allocated buffer with the Id of this object.
+ * This field is used for X.509 in PKCS#11 to make it easier to
+ * match a private key with a certificate. */
size_t objidlen;
unsigned char *objid;
@@ -144,8 +165,6 @@ struct cdf_object_s
size_t imagelen;
unsigned char *image;
- /* Set to true if a length and offset is available. */
- int have_off;
/* The offset and length of the object. They are only valid if
HAVE_OFF is true and set to 0 if HAVE_OFF is false. */
unsigned long off, len;
@@ -169,6 +188,37 @@ struct prkdf_object_s
/* Link to next item when used in a linked list. */
struct prkdf_object_s *next;
+ /* Flags to indicate whether fields are valid. */
+ unsigned int keygrip_valid:1;
+ unsigned int key_reference_valid:1;
+ unsigned int have_off:1;
+
+ /* Flag indicating that the corresponding PIN has already been
+ * verified. */
+ unsigned int pin_verified:1;
+
+ /* The key's usage flags. */
+ keyusage_flags_t usageflags;
+
+ /* The keygrip of the key. This is used as a cache. */
+ char keygrip[2*KEYGRIP_LEN+1];
+
+ /* The Gcrypt algo identifier for the key. It is valid if the
+ * keygrip is also valid. */
+ int keyalgo;
+
+ /* The length of the key in bits (e.g. for RSA the length of the
+ * modulus). It is valid if the keygrip is also valid. */
+ unsigned int keynbits;
+
+ /* Malloced CN from the Subject-DN of the corresponding certificate
+ * or NULL if not known. */
+ char *common_name;
+
+ /* Malloced SerialNumber from the Subject-DN of the corresponding
+ * certificate or NULL if not known. */
+ char *serial_number;
+
/* Length and allocated buffer with the Id of this object. */
size_t objidlen;
unsigned char *objid;
@@ -178,17 +228,11 @@ struct prkdf_object_s
size_t authidlen;
unsigned char *authid;
- /* The key's usage flags. */
- keyusage_flags_t usageflags;
-
/* The keyReference and a flag telling whether it is valid. */
unsigned long key_reference;
- int key_reference_valid;
- /* Set to true if a length and offset is available. */
- int have_off;
/* The offset and length of the object. They are only valid if
- HAVE_OFF is true and set to 0 if HAVE_OFF is false. */
+ * HAVE_OFF is true otherwise they are set to 0. */
unsigned long off, len;
/* The length of the path as given in the PrKDF and the path itself.
@@ -209,6 +253,9 @@ struct aodf_object_s
/* Link to next item when used in a linked list. */
struct aodf_object_s *next;
+ /* Flags to indicate whether fields are valid. */
+ unsigned int have_off:1;
+
/* Length and allocated buffer with the Id of this object. */
size_t objidlen;
unsigned char *objid;
@@ -218,6 +265,9 @@ struct aodf_object_s
size_t authidlen;
unsigned char *authid;
+ /* The file ID of this AODF. */
+ unsigned short fid;
+
/* The PIN Flags. */
struct
{
@@ -256,9 +306,6 @@ struct aodf_object_s
char pad_char;
int pad_char_valid;
-
- /* Set to true if a length and offset is available. */
- int have_off;
/* The offset and length of the object. They are only valid if
HAVE_OFF is true and set to 0 if HAVE_OFF is false. */
unsigned long off, len;
@@ -279,9 +326,12 @@ struct app_local_s
hierarchy. Thus we assume this is directly below the MF. */
unsigned short home_df;
- /* The type of the card. */
+ /* The type of the card's OS. */
card_type_t card_type;
+ /* The vendor's product. */
+ card_product_t card_product;
+
/* Flag indicating whether we may use direct path selection. */
int direct_path_selection;
@@ -304,6 +354,9 @@ struct app_local_s
unsigned char *serialno;
size_t serialnolen;
+ /* The manufacturerID from the TokenInfo EF. Malloced. */
+ char *manufacturer_id;
+
/* Information on all certificates. */
cdf_object_t certificate_info;
/* Information on all trusted certificates. */
@@ -321,8 +374,11 @@ struct app_local_s
/*** Local prototypes. ***/
+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);
+static char *get_dispserialno (app_t app, prkdf_object_t prkdf);
+static gpg_error_t do_getattr (app_t app, ctrl_t ctrl, const char *name);
@@ -347,6 +403,8 @@ release_prkdflist (prkdf_object_t a)
while (a)
{
prkdf_object_t tmp = a->next;
+ xfree (a->common_name);
+ xfree (a->serial_number);
xfree (a->objid);
xfree (a->authid);
xfree (a);
@@ -391,6 +449,7 @@ do_deinit (app_t app)
release_cdflist (app->app_local->useful_certificate_info);
release_prkdflist (app->app_local->private_key_info);
release_aodflist (app->app_local->auth_object_info);
+ xfree (app->app_local->manufacturer_id);
xfree (app->app_local->serialno);
xfree (app->app_local);
app->app_local = NULL;
@@ -412,14 +471,14 @@ select_and_read_binary (int slot, unsigned short efid, const char *efid_desc,
err = iso7816_select_file (slot, efid, 0);
if (err)
{
- log_error ("error selecting %s (0x%04X): %s\n",
+ log_error ("p15: error selecting %s (0x%04X): %s\n",
efid_desc, efid, gpg_strerror (err));
return err;
}
err = iso7816_read_binary (slot, 0, 0, buffer, buflen);
if (err)
{
- log_error ("error reading %s (0x%04X): %s\n",
+ log_error ("p15: error reading %s (0x%04X): %s\n",
efid_desc, efid, gpg_strerror (err));
return err;
}
@@ -439,14 +498,14 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
return gpg_error (GPG_ERR_INV_VALUE);
if (pathlen && *path != 0x3f00 )
- log_debug ("WARNING: relative path selection not yet implemented\n");
+ log_error ("p15: warning: relative path selection not yet implemented\n");
if (app->app_local->direct_path_selection)
{
err = iso7816_select_path (app->slot, path+1, pathlen-1);
if (err)
{
- log_error ("error selecting path ");
+ log_error ("p15: error selecting path ");
for (j=0; j < pathlen; j++)
log_printf ("%04hX", path[j]);
log_printf (": %s\n", gpg_strerror (err));
@@ -464,7 +523,7 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
err = iso7816_select_file (app->slot, path[i], !(i+1 == pathlen));
if (err)
{
- log_error ("error selecting part %d from path ", i);
+ log_error ("p15: error selecting part %d from path ", i);
for (j=0; j < pathlen; j++)
log_printf ("%04hX", path[j]);
log_printf (": %s\n", gpg_strerror (err));
@@ -492,35 +551,55 @@ parse_certid (app_t app, const char *certid,
*r_objid = NULL;
*r_objidlen = 0;
- if (app->app_local->home_df)
- snprintf (tmpbuf, sizeof tmpbuf,
- "P15-%04X.", (unsigned int)(app->app_local->home_df & 0xffff));
- else
- strcpy (tmpbuf, "P15.");
- if (strncmp (certid, tmpbuf, strlen (tmpbuf)) )
- {
- if (!strncmp (certid, "P15.", 4)
- || (!strncmp (certid, "P15-", 4)
- && hexdigitp (certid+4)
- && hexdigitp (certid+5)
- && hexdigitp (certid+6)
- && hexdigitp (certid+7)
- && certid[8] == '.'))
+ if (certid[0] != 'P' && strlen (certid) == 40) /* This is a keygrip. */
+ {
+ prkdf_object_t prkdf;
+
+ for (prkdf = app->app_local->private_key_info;
+ prkdf; prkdf = prkdf->next)
+ if (!keygrip_from_prkdf (app, prkdf)
+ && !strcmp (certid, prkdf->keygrip))
+ break;
+ if (!prkdf || !prkdf->objidlen || !prkdf->objid)
return gpg_error (GPG_ERR_NOT_FOUND);
- return gpg_error (GPG_ERR_INV_ID);
- }
- certid += strlen (tmpbuf);
-
- for (s=certid, objidlen=0; hexdigitp (s); s++, objidlen++)
- ;
- if (*s || !objidlen || (objidlen%2))
- return gpg_error (GPG_ERR_INV_ID);
- objidlen /= 2;
- objid = xtrymalloc (objidlen);
- if (!objid)
- return gpg_error_from_syserror ();
- for (s=certid, i=0; i < objidlen; i++, s+=2)
- objid[i] = xtoi_2 (s);
+ objidlen = prkdf->objidlen;
+ objid = xtrymalloc (objidlen);
+ if (!objid)
+ return gpg_error_from_syserror ();
+ memcpy (objid, prkdf->objid, prkdf->objidlen);
+ }
+ else /* This is a usual keyref. */
+ {
+ if (app->app_local->home_df)
+ snprintf (tmpbuf, sizeof tmpbuf, "P15-%04X.",
+ (unsigned int)(app->app_local->home_df & 0xffff));
+ else
+ strcpy (tmpbuf, "P15.");
+ if (strncmp (certid, tmpbuf, strlen (tmpbuf)) )
+ {
+ if (!strncmp (certid, "P15.", 4)
+ || (!strncmp (certid, "P15-", 4)
+ && hexdigitp (certid+4)
+ && hexdigitp (certid+5)
+ && hexdigitp (certid+6)
+ && hexdigitp (certid+7)
+ && certid[8] == '.'))
+ return gpg_error (GPG_ERR_NOT_FOUND);
+ return gpg_error (GPG_ERR_INV_ID);
+ }
+ certid += strlen (tmpbuf);
+ for (s=certid, objidlen=0; hexdigitp (s); s++, objidlen++)
+ ;
+ if (*s || !objidlen || (objidlen%2))
+ return gpg_error (GPG_ERR_INV_ID);
+ objidlen /= 2;
+ objid = xtrymalloc (objidlen);
+ if (!objid)
+ return gpg_error_from_syserror ();
+ for (s=certid, i=0; i < objidlen; i++, s+=2)
+ objid[i] = xtoi_2 (s);
+ }
+
*r_objid = objid;
*r_objidlen = objidlen;
return 0;
@@ -595,9 +674,9 @@ prkdf_object_from_keyidstr (app_t app, const char *keyidstr,
A0 06 30 04 04 02 60 34 = Private Keys
A4 06 30 04 04 02 60 35 = Certificates
- A5 06 30 04 04 02 60 36 = TrustedCertificates
- A7 06 30 04 04 02 60 37 = DataObjects
- A8 06 30 04 04 02 60 38 = AuthObjects
+ A5 06 30 04 04 02 60 36 = Trusted Certificates
+ A7 06 30 04 04 02 60 37 = Data Objects
+ A8 06 30 04 04 02 60 38 = Auth Objects
These are all PathOrObjects using the path CHOICE element. The
paths are octet strings of length 2. Using this Path CHOICE
@@ -608,9 +687,10 @@ read_ef_odf (app_t app, unsigned short odf_fid)
{
gpg_error_t err;
unsigned char *buffer, *p;
- size_t buflen;
+ size_t buflen, n;
unsigned short value;
size_t offset;
+ unsigned short home_df = 0;
err = select_and_read_binary (app->slot, odf_fid, "ODF", &buffer, &buflen);
if (err)
@@ -618,10 +698,12 @@ read_ef_odf (app_t app, unsigned short odf_fid)
if (buflen < 8)
{
- log_error ("error: ODF too short\n");
+ log_error ("p15: error: ODF too short\n");
xfree (buffer);
return gpg_error (GPG_ERR_INV_OBJ);
}
+
+ home_df = app->app_local->home_df;
p = buffer;
while (buflen && *p && *p != 0xff)
{
@@ -634,17 +716,35 @@ read_ef_odf (app_t app, unsigned short odf_fid)
else if ( buflen >= 12
&& (p[0] & 0xf0) == 0xA0
&& !memcmp (p+1, "\x0a\x30\x08\x04\x06\x3F\x00", 7)
- && app->app_local->home_df == ((p[8]<<8)|p[9]) )
+ && (!home_df || home_df == ((p[8]<<8)|p[9])) )
{
+ /* If we do not know the home DF, we take it from the first
+ * ODF object. Here are sample values:
+ * a0 0a 30 08 0406 3f00 5015 4401
+ * a1 0a 30 08 0406 3f00 5015 4411
+ * a4 0a 30 08 0406 3f00 5015 4441
+ * a5 0a 30 08 0406 3f00 5015 4451
+ * a8 0a 30 08 0406 3f00 5015 4481
+ * 00000000 */
+ if (!home_df)
+ {
+ home_df = ((p[8]<<8)|p[9]);
+ app->app_local->home_df = home_df;
+ log_info ("p15: application directory detected as 0x%04hX\n",
+ home_df);
+ /* We assume that direct path selection is possible. */
+ app->app_local->direct_path_selection = 1;
+ }
+
/* We only allow a full path if all files are at the same
- level and below the home directory. The extend this we
+ level and below the home directory. To extend this we
would need to make use of new data type capable of
keeping a full path. */
offset = 10;
}
else
{
- log_error ("ODF format is not supported by us\n");
+ log_printhex (p, buflen, "p15: ODF format not supported:");
xfree (buffer);
return gpg_error (GPG_ERR_INV_OBJ);
}
@@ -663,7 +763,8 @@ read_ef_odf (app_t app, unsigned short odf_fid)
}
if (value)
{
- log_error ("duplicate object type %d in ODF ignored\n",(p[0]&0x0f));
+ log_error ("p15: duplicate object type %d in ODF ignored\n",
+ (p[0]&0x0f));
continue;
}
value = ((p[offset] << 8) | p[offset+1]);
@@ -679,7 +780,8 @@ read_ef_odf (app_t app, unsigned short odf_fid)
case 7: app->app_local->odf.data_objects = value; break;
case 8: app->app_local->odf.auth_objects = value; break;
default:
- log_error ("unknown object type %d in ODF ignored\n", (p[0]&0x0f));
+ log_error ("p15: unknown object type %d in ODF ignored\n",
+ (p[0]&0x0f));
}
offset += 2;
@@ -690,8 +792,16 @@ read_ef_odf (app_t app, unsigned short odf_fid)
}
if (buflen)
- log_info ("warning: %u bytes of garbage detected at end of ODF\n",
- (unsigned int)buflen);
+ {
+ /* Print a warning if non-null garbage is left over. */
+ for (n=0; n < buflen && !p[n]; n++)
+ ;
+ if (n < buflen)
+ {
+ log_info ("p15: warning: garbage detected at end of ODF: ");
+ log_printhex (p, buflen, "");
+ }
+ }
xfree (buffer);
return 0;
@@ -861,7 +971,8 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
{
- log_error ("error parsing PrKDF record: %s\n", gpg_strerror (err));
+ log_error ("p15: error parsing PrKDF record: %s\n",
+ gpg_strerror (err));
goto leave;
}
pp = p;
@@ -1202,38 +1313,41 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
}
- log_debug ("PrKDF %04hX: id=", fid);
- for (i=0; i < prkdf->objidlen; i++)
- log_printf ("%02X", prkdf->objid[i]);
- log_printf (" path=");
- for (i=0; i < prkdf->pathlen; i++)
- log_printf ("%04hX", prkdf->path[i]);
- if (prkdf->have_off)
- log_printf ("[%lu/%lu]", prkdf->off, prkdf->len);
- if (prkdf->authid)
- {
- log_printf (" authid=");
- for (i=0; i < prkdf->authidlen; i++)
- log_printf ("%02X", prkdf->authid[i]);
- }
- if (prkdf->key_reference_valid)
- log_printf (" keyref=0x%02lX", prkdf->key_reference);
- log_printf (" usage=");
- s = "";
- if (prkdf->usageflags.encrypt) log_printf ("%sencrypt", s), s = ",";
- if (prkdf->usageflags.decrypt) log_printf ("%sdecrypt", s), s = ",";
- if (prkdf->usageflags.sign ) log_printf ("%ssign", s), s = ",";
- if (prkdf->usageflags.sign_recover)
- log_printf ("%ssign_recover", s), s = ",";
- if (prkdf->usageflags.wrap ) log_printf ("%swrap", s), s = ",";
- if (prkdf->usageflags.unwrap ) log_printf ("%sunwrap", s), s = ",";
- if (prkdf->usageflags.verify ) log_printf ("%sverify", s), s = ",";
- if (prkdf->usageflags.verify_recover)
- log_printf ("%sverify_recover", s), s = ",";
- if (prkdf->usageflags.derive ) log_printf ("%sderive", s), s = ",";
- if (prkdf->usageflags.non_repudiation)
- log_printf ("%snon_repudiation", s), s = ",";
- log_printf ("\n");
+ if (opt.verbose)
+ {
+ log_info ("p15: PrKDF %04hX: id=", fid);
+ for (i=0; i < prkdf->objidlen; i++)
+ log_printf ("%02X", prkdf->objid[i]);
+ log_printf (" path=");
+ for (i=0; i < prkdf->pathlen; i++)
+ log_printf ("%s%04hX", i?"/":"",prkdf->path[i]);
+ if (prkdf->have_off)
+ log_printf ("[%lu/%lu]", prkdf->off, prkdf->len);
+ if (prkdf->authid)
+ {
+ log_printf (" authid=");
+ for (i=0; i < prkdf->authidlen; i++)
+ log_printf ("%02X", prkdf->authid[i]);
+ }
+ if (prkdf->key_reference_valid)
+ log_printf (" keyref=0x%02lX", prkdf->key_reference);
+ log_info ("p15: usage=");
+ s = "";
+ if (prkdf->usageflags.encrypt) log_printf ("%sencrypt", s), s = ",";
+ if (prkdf->usageflags.decrypt) log_printf ("%sdecrypt", s), s = ",";
+ if (prkdf->usageflags.sign ) log_printf ("%ssign", s), s = ",";
+ if (prkdf->usageflags.sign_recover)
+ log_printf ("%ssign_recover", s), s = ",";
+ if (prkdf->usageflags.wrap ) log_printf ("%swrap", s), s = ",";
+ if (prkdf->usageflags.unwrap ) log_printf ("%sunwrap", s), s = ",";
+ if (prkdf->usageflags.verify ) log_printf ("%sverify", s), s = ",";
+ if (prkdf->usageflags.verify_recover)
+ log_printf ("%sverify_recover", s), s = ",";
+ if (prkdf->usageflags.derive ) log_printf ("%sderive", s), s = ",";
+ if (prkdf->usageflags.non_repudiation)
+ log_printf ("%snon_repudiation", s), s = ",";
+ log_printf ("\n");
+ }
/* Put it into the list. */
prkdf->next = prkdflist;
@@ -1242,7 +1356,7 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
continue; /* Ready. */
parse_error:
- log_error ("error parsing PrKDF record (%d): %s - skipped\n",
+ log_error ("p15: error parsing PrKDF record (%d): %s - skipped\n",
where, errstr? errstr : gpg_strerror (err));
if (prkdf)
{
@@ -1309,7 +1423,7 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
{
- log_error ("error parsing CDF record: %s\n", gpg_strerror (err));
+ log_error ("p15: error parsing CDF record: %s\n", gpg_strerror (err));
goto leave;
}
pp = p;
@@ -1470,15 +1584,18 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
cdf->len = ul;
}
- log_debug ("CDF %04hX: id=", fid);
- for (i=0; i < cdf->objidlen; i++)
- log_printf ("%02X", cdf->objid[i]);
- log_printf (" path=");
- for (i=0; i < cdf->pathlen; i++)
- log_printf ("%04hX", cdf->path[i]);
- if (cdf->have_off)
- log_printf ("[%lu/%lu]", cdf->off, cdf->len);
- log_printf ("\n");
+ if (opt.verbose)
+ {
+ log_info ("p15: CDF %04hX: id=", fid);
+ for (i=0; i < cdf->objidlen; i++)
+ log_printf ("%02X", cdf->objid[i]);
+ log_printf (" path=");
+ for (i=0; i < cdf->pathlen; i++)
+ log_printf ("%s%04hX", i?"/":"", cdf->path[i]);
+ if (cdf->have_off)
+ log_printf ("[%lu/%lu]", cdf->off, cdf->len);
+ log_printf ("\n");
+ }
/* Put it into the list. */
cdf->next = cdflist;
@@ -1487,7 +1604,7 @@ read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result)
continue; /* Ready. */
parse_error:
- log_error ("error parsing CDF record (%d): %s - skipped\n",
+ log_error ("p15: error parsing CDF record (%d): %s - skipped\n",
where, errstr? errstr : gpg_strerror (err));
xfree (cdf);
err = 0;
@@ -1583,7 +1700,8 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
{
- log_error ("error parsing AODF record: %s\n", gpg_strerror (err));
+ log_error ("p15: error parsing AODF record: %s\n",
+ gpg_strerror (err));
goto leave;
}
pp = p;
@@ -1595,6 +1713,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
aodf = xtrycalloc (1, sizeof *aodf);
if (!aodf)
goto no_core;
+ aodf->fid = fid;
/* Parse the commonObjectAttributes. */
where = __LINE__;
@@ -2057,73 +2176,77 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
extensions of pkcs#15. */
ready:
- log_debug ("AODF %04hX: id=", fid);
- for (i=0; i < aodf->objidlen; i++)
- log_printf ("%02X", aodf->objid[i]);
- if (aodf->authid)
- {
- log_printf (" authid=");
- for (i=0; i < aodf->authidlen; i++)
- log_printf ("%02X", aodf->authid[i]);
- }
- log_printf (" flags=");
- s = "";
- if (aodf->pinflags.case_sensitive)
- log_printf ("%scase_sensitive", s), s = ",";
- if (aodf->pinflags.local)
- log_printf ("%slocal", s), s = ",";
- if (aodf->pinflags.change_disabled)
- log_printf ("%schange_disabled", s), s = ",";
- if (aodf->pinflags.unblock_disabled)
- log_printf ("%sunblock_disabled", s), s = ",";
- if (aodf->pinflags.initialized)
- log_printf ("%sinitialized", s), s = ",";
- if (aodf->pinflags.needs_padding)
- log_printf ("%sneeds_padding", s), s = ",";
- if (aodf->pinflags.unblocking_pin)
- log_printf ("%sunblocking_pin", s), s = ",";
- if (aodf->pinflags.so_pin)
- log_printf ("%sso_pin", s), s = ",";
- if (aodf->pinflags.disable_allowed)
- log_printf ("%sdisable_allowed", s), s = ",";
- if (aodf->pinflags.integrity_protected)
- log_printf ("%sintegrity_protected", s), s = ",";
- if (aodf->pinflags.confidentiality_protected)
- log_printf ("%sconfidentiality_protected", s), s = ",";
- if (aodf->pinflags.exchange_ref_data)
- log_printf ("%sexchange_ref_data", s), s = ",";
- {
- char numbuf[50];
- switch (aodf->pintype)
+ if (opt.verbose)
+ {
+ log_info ("p15: AODF %04hX: id=", fid);
+ for (i=0; i < aodf->objidlen; i++)
+ log_printf ("%02X", aodf->objid[i]);
+ if (aodf->authid)
+ {
+ log_printf (" authid=");
+ for (i=0; i < aodf->authidlen; i++)
+ log_printf ("%02X", aodf->authid[i]);
+ }
+ if (aodf->pin_reference_valid)
+ log_printf (" pinref=0x%02lX", aodf->pin_reference);
+ if (aodf->pathlen)
+ {
+ log_printf (" path=");
+ for (i=0; i < aodf->pathlen; i++)
+ log_printf ("%s%04hX", i?"/":"",aodf->path[i]);
+ if (aodf->have_off)
+ log_printf ("[%lu/%lu]", aodf->off, aodf->len);
+ }
+ log_printf (" min=%lu", aodf->min_length);
+ log_printf (" stored=%lu", aodf->stored_length);
+ if (aodf->max_length_valid)
+ log_printf (" max=%lu", aodf->max_length);
+ if (aodf->pad_char_valid)
+ log_printf (" pad=0x%02x", aodf->pad_char);
+
+ log_info ("p15: flags=");
+ s = "";
+ if (aodf->pinflags.case_sensitive)
+ log_printf ("%scase_sensitive", s), s = ",";
+ if (aodf->pinflags.local)
+ log_printf ("%slocal", s), s = ",";
+ if (aodf->pinflags.change_disabled)
+ log_printf ("%schange_disabled", s), s = ",";
+ if (aodf->pinflags.unblock_disabled)
+ log_printf ("%sunblock_disabled", s), s = ",";
+ if (aodf->pinflags.initialized)
+ log_printf ("%sinitialized", s), s = ",";
+ if (aodf->pinflags.needs_padding)
+ log_printf ("%sneeds_padding", s), s = ",";
+ if (aodf->pinflags.unblocking_pin)
+ log_printf ("%sunblocking_pin", s), s = ",";
+ if (aodf->pinflags.so_pin)
+ log_printf ("%sso_pin", s), s = ",";
+ if (aodf->pinflags.disable_allowed)
+ log_printf ("%sdisable_allowed", s), s = ",";
+ if (aodf->pinflags.integrity_protected)
+ log_printf ("%sintegrity_protected", s), s = ",";
+ if (aodf->pinflags.confidentiality_protected)
+ log_printf ("%sconfidentiality_protected", s), s = ",";
+ if (aodf->pinflags.exchange_ref_data)
+ log_printf ("%sexchange_ref_data", s), s = ",";
{
- case PIN_TYPE_BCD: s = "bcd"; break;
- case PIN_TYPE_ASCII_NUMERIC: s = "ascii-numeric"; break;
- case PIN_TYPE_UTF8: s = "utf8"; break;
- case PIN_TYPE_HALF_NIBBLE_BCD: s = "half-nibble-bcd"; break;
- case PIN_TYPE_ISO9564_1: s = "iso9564-1"; break;
- default:
- sprintf (numbuf, "%lu", (unsigned long)aodf->pintype);
- s = numbuf;
+ char numbuf[50];
+ switch (aodf->pintype)
+ {
+ case PIN_TYPE_BCD: s = "bcd"; break;
+ case PIN_TYPE_ASCII_NUMERIC: s = "ascii-numeric"; break;
+ case PIN_TYPE_UTF8: s = "utf8"; break;
+ case PIN_TYPE_HALF_NIBBLE_BCD: s = "half-nibble-bcd"; break;
+ case PIN_TYPE_ISO9564_1: s = "iso9564-1"; break;
+ default:
+ sprintf (numbuf, "%lu", (unsigned long)aodf->pintype);
+ s = numbuf;
+ }
+ log_printf (" type=%s", s);
}
- log_printf (" type=%s", s);
- }
- log_printf (" min=%lu", aodf->min_length);
- log_printf (" stored=%lu", aodf->stored_length);
- if (aodf->max_length_valid)
- log_printf (" max=%lu", aodf->max_length);
- if (aodf->pad_char_valid)
- log_printf (" pad=0x%02x", aodf->pad_char);
- if (aodf->pin_reference_valid)
- log_printf (" pinref=0x%02lX", aodf->pin_reference);
- if (aodf->pathlen)
- {
- log_printf (" path=");
- for (i=0; i < aodf->pathlen; i++)
- log_printf ("%04hX", aodf->path[i]);
- if (aodf->have_off)
- log_printf ("[%lu/%lu]", aodf->off, aodf->len);
+ log_printf ("\n");
}
- log_printf ("\n");
/* Put it into the list. */
aodf->next = aodflist;
@@ -2137,7 +2260,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
goto leave;
parse_error:
- log_error ("error parsing AODF record (%d): %s - skipped\n",
+ log_error ("p15: error parsing AODF record (%d): %s - skipped\n",
where, errstr? errstr : gpg_strerror (err));
err = 0;
release_aodf_object (aodf);
@@ -2153,6 +2276,62 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
}
+/* Print the BIT STRING with the tokenflags from the TokenInfo. */
+static void
+print_tokeninfo_tokenflags (const unsigned char *der, size_t derlen)
+{
+ unsigned int bits, mask;
+ int i, unused, full;
+ int other = 0;
+
+ if (!derlen)
+ {
+ log_printf (" [invalid object]");
+ return;
+ }
+
+ unused = *der++; derlen--;
+ if ((!derlen && unused) || unused/8 > derlen)
+ {
+ log_printf (" [wrong encoding]");
+ return;
+ }
+ full = derlen - (unused+7)/8;
+ unused %= 8;
+ mask = 0;
+ for (i=1; unused; i <<= 1, unused--)
+ mask |= i;
+
+ /* First octet */
+ if (derlen)
+ {
+ bits = *der++; derlen--;
+ if (full)
+ full--;
+ else
+ {
+ bits &= ~mask;
+ mask = 0;
+ }
+ }
+ else
+ bits = 0;
+ if ((bits & 0x80)) log_printf (" readonly");
+ if ((bits & 0x40)) log_printf (" loginRequired");
+ if ((bits & 0x20)) log_printf (" prnGeneration");
+ if ((bits & 0x10)) log_printf (" eidCompliant");
+ if ((bits & 0x08)) other = 1;
+ if ((bits & 0x04)) other = 1;
+ if ((bits & 0x02)) other = 1;
+ if ((bits & 0x01)) other = 1;
+
+ /* Next octet. */
+ if (derlen)
+ other = 1;
+
+ if (other)
+ log_printf (" [unknown]");
+}
@@ -2216,6 +2395,10 @@ read_ef_tokeninfo (app_t app)
int class, tag, constructed, ndef;
unsigned long ul;
+ xfree (app->app_local->manufacturer_id);
+ app->app_local->manufacturer_id = NULL;
+ app->app_local->card_product = CARD_PRODUCT_UNKNOWN;
+
err = select_and_read_binary (app->slot, 0x5032, "TokenInfo",
&buffer, &buflen);
if (err)
@@ -2230,7 +2413,7 @@ read_ef_tokeninfo (app_t app)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
{
- log_error ("error parsing TokenInfo: %s\n", gpg_strerror (err));
+ log_error ("p15: error parsing TokenInfo: %s\n", gpg_strerror (err));
goto leave;
}
@@ -2252,11 +2435,13 @@ read_ef_tokeninfo (app_t app)
}
if (ul)
{
- log_error ("invalid version %lu in TokenInfo\n", ul);
+ log_error ("p15: invalid version %lu in TokenInfo\n", ul);
err = gpg_error (GPG_ERR_INV_OBJ);
goto leave;
}
+ if (opt.verbose)
+ log_info ("p15: TokenInfo:\n");
/* serialNumber. */
err = parse_ber_header (&p, &n, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
@@ -2274,7 +2459,68 @@ read_ef_tokeninfo (app_t app)
}
memcpy (app->app_local->serialno, p, objlen);
app->app_local->serialnolen = objlen;
- log_printhex ("Serialnumber from EF(TokenInfo) is:", p, objlen);
+ if (opt.verbose)
+ {
+ /* (We use a separate log_info to avoid the "DBG:" prefix.) */
+ log_info ("p15: serialNumber .: ");
+ log_printhex (p, objlen, "");
+ }
+ p += objlen;
+ n -= objlen;
+
+ /* Is there an optional manufacturerID? */
+ err = parse_ber_header (&p, &n, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > n || !objlen))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ goto leave;
+ if (class == CLASS_UNIVERSAL && tag == TAG_UTF8_STRING)
+ {
+ if (opt.verbose)
+ log_info ("p15: manufacturerID: %.*s\n", (int)objlen, p);
+ app->app_local->manufacturer_id = percent_data_escape (0, NULL,
+ p, objlen);
+ p += objlen;
+ n -= objlen;
+ /* Get next TLV. */
+ err = parse_ber_header (&p, &n, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > n || !objlen))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ goto leave;
+ }
+ if (class == CLASS_CONTEXT && tag == 0)
+ {
+ if (opt.verbose)
+ log_info ("p15: label ........: %.*s\n", (int)objlen, p);
+ if (objlen > 15 && !memcmp (p, "D-TRUST Card V3", 15)
+ && app->app_local->card_type == CARD_TYPE_CARDOS_50)
+ app->app_local->card_product = CARD_PRODUCT_DTRUST;
+
+ p += objlen;
+ n -= objlen;
+ /* Get next TLV. */
+ err = parse_ber_header (&p, &n, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > n || !objlen))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ goto leave;
+ }
+ /* The next is the mandatory tokenflags object. */
+ if (class == CLASS_UNIVERSAL && tag == TAG_BIT_STRING)
+ {
+ if (opt.verbose)
+ {
+ log_info ("p15: tokenflags ...:");
+ print_tokeninfo_tokenflags (p, objlen);
+ log_printf ("\n");
+ }
+ p += objlen;
+ n -= objlen;
+ }
leave:
xfree (buffer);
@@ -2386,21 +2632,31 @@ send_certinfo (app_t app, ctrl_t ctrl, const char *certtype,
/* Get the keygrip of the private key object PRKDF. On success the
- keygrip gets returned in the caller provided 41 byte buffer
- R_GRIPSTR. */
+ * keygrip, the algo and the length are stored in the KEYGRIP,
+ * KEYALGO, and KEYNBITS fields of the PRKDF object. */
static gpg_error_t
-keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr)
+keygrip_from_prkdf (app_t app, prkdf_object_t prkdf)
{
gpg_error_t err;
cdf_object_t cdf;
unsigned char *der;
size_t derlen;
ksba_cert_t cert;
+ gcry_sexp_t s_pkey = NULL;
+
+ /* Easy if we got a cached version. */
+ if (prkdf->keygrip_valid)
+ return 0;
+
+ xfree (prkdf->common_name);
+ prkdf->common_name = NULL;
+ xfree (prkdf->serial_number);
+ prkdf->serial_number = NULL;
/* FIXME: We should check whether a public key directory file and a
matching public key for PRKDF is available. This should make
extraction of the key much easier. My current test card doesn't
- have one, so we can only use the fallback solution bu looking for
+ have one, so we can only use the fallback solution by looking for
a matching certificate and extract the key from there. */
/* Look for a matching certificate. A certificate matches if the Id
@@ -2420,67 +2676,172 @@ keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr)
&& !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen))
break;
if (!cdf)
- return gpg_error (GPG_ERR_NOT_FOUND);
+ {
+ err = gpg_error (GPG_ERR_NOT_FOUND);
+ goto leave;
+ }
err = readcert_by_cdf (app, cdf, &der, &derlen);
if (err)
- return err;
+ goto leave;
err = ksba_cert_new (&cert);
if (!err)
err = ksba_cert_init_from_mem (cert, der, derlen);
xfree (der);
if (!err)
- err = app_help_get_keygrip_string (cert, r_gripstr);
+ err = app_help_get_keygrip_string (cert, prkdf->keygrip, &s_pkey);
+ if (!err)
+ {
+ /* Try to get the CN and the SerialNumber from the certificate;
+ * we use a very simple approach here which should work in many
+ * cases. Eventually we should add a rfc-2253 parser into
+ * libksba to make it easier to parse such a string.
+ *
+ * First example string:
+ * "CN=Otto Schily,O=Miniluv,C=DE"
+ * Second example string:
+ * "2.5.4.5=#445452323030303236333531,2.5.4.4=#4B6F6368,"
+ * "2.5.4.42=#5765726E6572,CN=Werner Koch,OU=For testing"
+ * " purposes only!,O=Testorganisation,C=DE"
+ */
+ char *dn = ksba_cert_get_subject (cert, 0);
+ if (dn)
+ {
+ char *p, *pend, *buf;
+
+ p = strstr (dn, "CN=");
+ if (p && (p==dn || p[-1] == ','))
+ {
+ p += 3;
+ if (!(pend = strchr (p, ',')))
+ pend = p + strlen (p);
+ if (pend && pend > p
+ && (prkdf->common_name = xtrymalloc ((pend - p) + 1)))
+ {
+ memcpy (prkdf->common_name, p, pend-p);
+ prkdf->common_name[pend-p] = 0;
+ }
+ }
+ p = strstr (dn, "2.5.4.5=#"); /* OID of the SerialNumber */
+ if (p && (p==dn || p[-1] == ','))
+ {
+ p += 9;
+ if (!(pend = strchr (p, ',')))
+ pend = p + strlen (p);
+ if (pend && pend > p
+ && (buf = xtrymalloc ((pend - p) + 1)))
+ {
+ memcpy (buf, p, pend-p);
+ buf[pend-p] = 0;
+ if (!hex2str (buf, buf, strlen (buf)+1, NULL))
+ xfree (buf); /* Invalid hex encoding. */
+ else
+ prkdf->serial_number = buf;
+ }
+ }
+ ksba_free (dn);
+ }
+ }
+
ksba_cert_release (cert);
+ if (err)
+ goto leave;
+
+ prkdf->keyalgo = get_pk_algo_from_key (s_pkey);
+ if (!prkdf->keyalgo)
+ {
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+ goto leave;
+ }
+
+ prkdf->keynbits = gcry_pk_get_nbits (s_pkey);
+ if (!prkdf->keynbits)
+ {
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+ goto leave;
+ }
+
+ prkdf->keygrip_valid = 1; /* Yeah, got everything. */
+ leave:
+ gcry_sexp_release (s_pkey);
return err;
}
+/* Return a malloced keyref string for PRKDF. Returns NULL on
+ * malloc failure. */
+static char *
+keyref_from_prkdf (app_t app, prkdf_object_t prkdf)
+{
+ char *buf, *p;
+
+ buf = xtrymalloc (4 + 5 + prkdf->objidlen*2 + 1);
+ if (!buf)
+ return NULL;
+ p = stpcpy (buf, "P15");
+ if (app->app_local->home_df)
+ {
+ snprintf (p, 6, "-%04X",
+ (unsigned int)(app->app_local->home_df & 0xffff));
+ p += 5;
+ }
+ p = stpcpy (p, ".");
+ bin2hex (prkdf->objid, prkdf->objidlen, p);
+ return buf;
+}
/* Helper to do_learn_status: Send information about all known
keypairs back. FIXME: much code duplication from
send_certinfo(). */
static gpg_error_t
-send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo)
+send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t prkdf)
{
gpg_error_t err;
- for (; keyinfo; keyinfo = keyinfo->next)
+ for (; prkdf; prkdf = prkdf->next)
{
- char gripstr[40+1];
- char *buf, *p;
+ char *buf;
int j;
- buf = xtrymalloc (9 + keyinfo->objidlen*2 + 1);
+ buf = keyref_from_prkdf (app, prkdf);
if (!buf)
return gpg_error_from_syserror ();
- p = stpcpy (buf, "P15");
- if (app->app_local->home_df)
- {
- snprintf (p, 6, "-%04X",
- (unsigned int)(app->app_local->home_df & 0xffff));
- p += 5;
- }
- p = stpcpy (p, ".");
- bin2hex (keyinfo->objid, keyinfo->objidlen, p);
- err = keygripstr_from_prkdf (app, keyinfo, gripstr);
+ err = keygrip_from_prkdf (app, prkdf);
if (err)
{
- log_error ("can't get keygrip from ");
- for (j=0; j < keyinfo->pathlen; j++)
- log_printf ("%04hX", keyinfo->path[j]);
+ log_error ("p15: error getting keygrip from ");
+ for (j=0; j < prkdf->pathlen; j++)
+ log_printf ("%s%04hX", j?"/":"", prkdf->path[j]);
log_printf (": %s\n", gpg_strerror (err));
}
else
{
- assert (strlen (gripstr) == 40);
+ char usage[5];
+ size_t usagelen = 0;
+
+ if (prkdf->usageflags.sign
+ || prkdf->usageflags.sign_recover
+ || prkdf->usageflags.non_repudiation)
+ usage[usagelen++] = 's';
+ if (prkdf->usageflags.sign
+ || prkdf->usageflags.sign_recover)
+ usage[usagelen++] = 'c';
+ if (prkdf->usageflags.decrypt
+ || prkdf->usageflags.unwrap)
+ usage[usagelen++] = 'e';
+ if (prkdf->usageflags.sign
+ || prkdf->usageflags.sign_recover)
+ usage[usagelen++] = 'a';
+
+ log_assert (strlen (prkdf->keygrip) == 40);
send_status_info (ctrl, "KEYPAIRINFO",
- gripstr, 40,
+ prkdf->keygrip, 2*KEYGRIP_LEN,
buf, strlen (buf),
+ usage, usagelen,
NULL, (size_t)0);
}
xfree (buf);
@@ -2500,7 +2861,10 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
err = 0;
else
{
- err = send_certinfo (app, ctrl, "100", app->app_local->certificate_info);
+ err = do_getattr (app, ctrl, "MANUFACTURER");
+ if (!err)
+ err = send_certinfo (app, ctrl, "100",
+ app->app_local->certificate_info);
if (!err)
err = send_certinfo (app, ctrl, "101",
app->app_local->trusted_certificate_info);
@@ -2553,14 +2917,18 @@ readcert_by_cdf (app_t app, cdf_object_t cdf,
if (err)
goto leave;
- err = iso7816_read_binary (app->slot, cdf->off, cdf->len, &buffer, &buflen);
+ err = iso7816_read_binary_ext (app_get_slot (app), 1, cdf->off, cdf->len,
+ &buffer, &buflen);
if (!err && (!buflen || *buffer == 0xff))
err = gpg_error (GPG_ERR_NOT_FOUND);
if (err)
{
- log_error ("error reading certificate with Id ");
+ log_error ("p15: error reading certificate id=");
for (i=0; i < cdf->objidlen; i++)
log_printf ("%02X", cdf->objid[i]);
+ log_printf (" at ");
+ for (i=0; i < cdf->pathlen; i++)
+ log_printf ("%s%04hX", i? "/":"", cdf->path[i]);
log_printf (": %s\n", gpg_strerror (err));
goto leave;
}
@@ -2666,37 +3034,42 @@ static gpg_error_t
do_getattr (app_t app, ctrl_t ctrl, const char *name)
{
gpg_error_t err;
+ prkdf_object_t prkdf;
- if (!strcmp (name, "$AUTHKEYID"))
+ if (!strcmp (name, "$AUTHKEYID")
+ || !strcmp (name, "$ENCRKEYID")
+ || !strcmp (name, "$SIGNKEYID"))
{
- char *buf, *p;
- prkdf_object_t prkdf;
+ char *buf;
- /* We return the ID of the first private keycapable of
- signing. */
+ /* We return the ID of the first private key capable of the
+ * requested action. Note that we do not yet return
+ * non_repudiation keys for $SIGNKEYID because our D-Trust
+ * testcard uses rsaPSS, which is not supported by gpgsm and not
+ * covered by the VS-NfD approval. */
for (prkdf = app->app_local->private_key_info; prkdf;
prkdf = prkdf->next)
- if (prkdf->usageflags.sign)
- break;
+ {
+ if (name[1] == 'A' && (prkdf->usageflags.sign
+ || prkdf->usageflags.sign_recover))
+ break;
+ else if (name[1] == 'E' && (prkdf->usageflags.decrypt
+ || prkdf->usageflags.unwrap))
+ break;
+ else if (name[1] == 'S' && (prkdf->usageflags.sign
+ || prkdf->usageflags.sign_recover))
+ break;
+ }
if (prkdf)
{
- buf = xtrymalloc (9 + prkdf->objidlen*2 + 1);
+ buf = keyref_from_prkdf (app, prkdf);
if (!buf)
return gpg_error_from_syserror ();
- p = stpcpy (buf, "P15");
- if (app->app_local->home_df)
- {
- snprintf (p, 6, "-%04X",
- (unsigned int)(app->app_local->home_df & 0xffff));
- p += 5;
- }
- p = stpcpy (p, ".");
- bin2hex (prkdf->objid, prkdf->objidlen, p);
send_status_info (ctrl, name, buf, strlen (buf), NULL, 0);
xfree (buf);
- return 0;
}
+ return 0;
}
else if (!strcmp (name, "$DISPSERIALNO"))
{
@@ -2716,7 +3089,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
if (err)
{
- log_error ("error accessing EF(ID): %s\n", gpg_strerror (err));
+ log_error ("p15: error accessing EF(ID): %s\n",
+ gpg_strerror (err));
return err;
}
@@ -2736,7 +3110,41 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
}
xfree (buffer);
}
-
+ else
+ {
+ /* We use the first private key object which has a serial
+ * number set. If none was found, we parse the first
+ * object and see whether this has then a serial number. */
+ for (prkdf = app->app_local->private_key_info; prkdf;
+ prkdf = prkdf->next)
+ if (prkdf->serial_number)
+ break;
+ if (!prkdf && app->app_local->private_key_info)
+ {
+ prkdf = app->app_local->private_key_info;
+ keygrip_from_prkdf (app, prkdf);
+ if (!prkdf->serial_number)
+ prkdf = NULL;
+ }
+ if (prkdf)
+ {
+ char *sn = get_dispserialno (app, prkdf);
+ /* Unless there is a bogus S/N in the cert we should
+ * have a suitable one from the cert here now. */
+ err = send_status_printf (ctrl, name, "%s", sn);
+ xfree (sn);
+ return err;
+ }
+ }
+ /* No abbreviated serial number. */
+ }
+ else if (!strcmp (name, "MANUFACTURER"))
+ {
+ if (app->app_local->manufacturer_id)
+ return send_status_printf (ctrl, "MANUFACTURER", "0 %s",
+ app->app_local->manufacturer_id);
+ else
+ return 0;
}
return gpg_error (GPG_ERR_INV_NAME);
}
@@ -2761,7 +3169,7 @@ micardo_mse (app_t app, unsigned short fid)
err = iso7816_select_file (app->slot, 0x0013, 0);
if (err)
{
- log_error ("error reading EF_keyD: %s\n", gpg_strerror (err));
+ log_error ("p15: error reading EF_keyD: %s\n", gpg_strerror (err));
return err;
}
@@ -2777,11 +3185,15 @@ micardo_mse (app_t app, unsigned short fid)
break; /* ready */
if (err)
{
- log_error ("error reading EF_keyD record: %s\n",
+ log_error ("p15: error reading EF_keyD record: %s\n",
gpg_strerror (err));
return err;
}
- log_printhex ("keyD record:", buffer, buflen);
+ if (opt.verbose)
+ {
+ log_info (buffer, buflen, "p15: keyD record: ");
+ log_printhex (buffer, buflen, "");
+ }
p = find_tlv (buffer, buflen, 0x83, &n);
if (p && n == 4 && ((p[2]<<8)|p[3]) == fid)
{
@@ -2803,7 +3215,7 @@ micardo_mse (app_t app, unsigned short fid)
}
if (se_num == -1)
{
- log_error ("CRT for keyfile %04hX not found\n", fid);
+ log_error ("p15: CRT for keyfile %04hX not found\n", fid);
return gpg_error (GPG_ERR_NOT_FOUND);
}
@@ -2814,7 +3226,7 @@ micardo_mse (app_t app, unsigned short fid)
err = iso7816_manage_security_env (app->slot, 0xf3, se_num, NULL, 0);
if (err)
{
- log_error ("restoring SE to %d failed: %s\n",
+ log_error ("p15: restoring SE to %d failed: %s\n",
se_num, gpg_strerror (err));
return err;
}
@@ -2829,7 +3241,7 @@ micardo_mse (app_t app, unsigned short fid)
err = iso7816_manage_security_env (app->slot, 0x41, 0xb6, msebuf, 5);
if (err)
{
- log_error ("setting SE to reference file %04hX failed: %s\n",
+ log_error ("p15: setting SE to reference file %04hX failed: %s\n",
refdata, gpg_strerror (err));
return err;
}
@@ -2838,6 +3250,372 @@ micardo_mse (app_t app, unsigned short fid)
+/* Prepare the verification of the PIN for the key PRKDF by checking
+ * the AODF and selecting the key file. KEYREF is used for error
+ * messages. */
+static gpg_error_t
+prepare_verify_pin (app_t app, const char *keyref,
+ prkdf_object_t prkdf, aodf_object_t aodf)
+{
+ gpg_error_t err;
+ int i;
+
+ if (opt.verbose)
+ {
+ log_info ("p15: using AODF %04hX id=", aodf->fid);
+ for (i=0; i < aodf->objidlen; i++)
+ log_printf ("%02X", aodf->objid[i]);
+ log_printf ("\n");
+ }
+
+ if (aodf->authid && opt.verbose)
+ log_info ("p15: PIN is controlled by another authentication token\n");
+
+ if (aodf->pinflags.integrity_protected
+ || aodf->pinflags.confidentiality_protected)
+ {
+ log_error ("p15: "
+ "PIN verification requires unsupported protection method\n");
+ return gpg_error (GPG_ERR_BAD_PIN_METHOD);
+ }
+ if (!aodf->stored_length && aodf->pinflags.needs_padding)
+ {
+ log_error ("p15: "
+ "PIN verification requires padding but no length known\n");
+ return gpg_error (GPG_ERR_INV_CARD);
+ }
+
+
+ if (app->app_local->card_product == CARD_PRODUCT_DTRUST)
+ {
+ /* According to our protocol analysis we need to select a
+ * special AID here. Before that the master file needs to be
+ * selected. (RID A000000167 is assigned to IBM) */
+ static char const dtrust_aid[] =
+ { 0xA0, 0x00, 0x00, 0x01, 0x67, 0x45, 0x53, 0x49, 0x47, 0x4E };
+
+ err = iso7816_select_mf (app_get_slot (app));
+ if (!err)
+ err = iso7816_select_application (app_get_slot (app),
+ dtrust_aid, sizeof dtrust_aid, 0);
+ if (err)
+ log_error ("p15: error selecting D-TRUST's AID for key %s: %s\n",
+ keyref, gpg_strerror (err));
+ }
+ else
+ {
+ /* Standard case: Select the key file. Note that this may
+ * change the security environment thus we need to do it before
+ * PIN verification. */
+ err = select_ef_by_path (app, prkdf->path, prkdf->pathlen);
+ if (err)
+ log_error ("p15: error selecting file for key %s: %s\n",
+ keyref, gpg_strerror (err));
+ }
+
+ return err;
+}
+
+
+static int
+any_control_or_space (const char *string)
+{
+ const unsigned char *s;
+
+ for (s = string; *string; string++)
+ if (*s <= 0x20 || *s >= 0x7f)
+ return 1;
+ return 0;
+}
+
+
+/* Return a malloced serial number to be shown to the user. PRKDF is
+ * used to get it from a certificate; PRKDF may be NULL. */
+static char *
+get_dispserialno (app_t app, prkdf_object_t prkdf)
+{
+ char *serial;
+
+ /* We prefer the SerialNumber RDN from the Subject-DN but we don't
+ * use it if it features a percent sign (special character in pin
+ * prompts) or has any control character. */
+ if (prkdf && prkdf->serial_number && *prkdf->serial_number
+ && !strchr (prkdf->serial_number, '%')
+ && !any_control_or_space (prkdf->serial_number))
+ {
+ serial = xtrystrdup (prkdf->serial_number);
+ }
+ else
+ {
+ serial = app_get_serialno (app);
+ }
+ return serial;
+}
+
+
+/* Return an allocated string to be used as prompt. Returns NULL on
+ * malloc error. */
+static char *
+make_pin_prompt (app_t app, int remaining, const char *firstline,
+ prkdf_object_t prkdf)
+{
+ char *serial, *tmpbuf, *result;
+
+ serial = get_dispserialno (app, prkdf);
+
+ /* TRANSLATORS: Put a \x1f right before a colon. This can be
+ * used by pinentry to nicely align the names and values. Keep
+ * the %s at the start and end of the string. */
+ result = xtryasprintf (_("%s"
+ "Number\x1f: %s%%0A"
+ "Holder\x1f: %s"
+ "%s"),
+ "\x1e",
+ serial,
+ prkdf->common_name? prkdf->common_name: "",
+ "");
+ xfree (serial);
+ if (!result)
+ return NULL; /* Out of core. */
+
+ /* Append a "remaining attempts" info if needed. */
+ if (remaining != -1 && remaining < 3)
+ {
+ char *rembuf;
+
+ /* TRANSLATORS: This is the number of remaining attempts to
+ * enter a PIN. Use %%0A (double-percent,0A) for a linefeed. */
+ rembuf = xtryasprintf (_("Remaining attempts: %d"), remaining);
+ if (rembuf)
+ {
+ tmpbuf = strconcat (firstline, "%0A%0A", result,
+ "%0A%0A", rembuf, NULL);
+ xfree (rembuf);
+ }
+ else
+ tmpbuf = NULL;
+ xfree (result);
+ result = tmpbuf;
+ }
+ else
+ {
+ tmpbuf = strconcat (firstline, "%0A%0A", result, NULL);
+ xfree (result);
+ result = tmpbuf;
+ }
+
+ return result;
+}
+
+
+/* Given the private key object PRKDF and its authentication object
+ * AODF ask for the PIN and verify that PIN. */
+static gpg_error_t
+verify_pin (app_t app,
+ gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg,
+ prkdf_object_t prkdf, aodf_object_t aodf)
+{
+ gpg_error_t err;
+ char *pinvalue;
+ size_t pinvaluelen;
+ const char *label;
+ const char *errstr;
+ const char *s;
+ int remaining;
+ int pin_reference;
+ int i;
+
+ if (!aodf)
+ return 0;
+
+ pin_reference = aodf->pin_reference_valid? aodf->pin_reference : 0;
+
+ if (app->app_local->card_type == CARD_TYPE_CARDOS_50)
+ {
+ /* We know that this card supports a verify status check. Note
+ * that in contrast to PIV cards ISO7816_VERIFY_NOT_NEEDED is
+ * not supported. */
+ remaining = iso7816_verify_status (app_get_slot (app), pin_reference);
+ if (remaining < 0)
+ remaining = -1; /* We don't care about the concrete error. */
+ if (remaining < 3)
+ {
+ if (remaining >= 0)
+ log_info ("p15: PIN has %d attempts left\n", remaining);
+ /* On error or if less than 3 better ask. */
+ prkdf->pin_verified = 0;
+ }
+ }
+ else
+ remaining = -1; /* Unknown. */
+
+ /* Check whether we already verified it. */
+ if (prkdf->pin_verified)
+ return 0; /* Already done. */
+
+ if (prkdf->usageflags.non_repudiation
+ && (app->app_local->card_type == CARD_TYPE_BELPIC
+ || app->app_local->card_product == CARD_PRODUCT_DTRUST))
+ label = _("||Please enter the PIN for the key to create "
+ "qualified signatures.");
+ else
+ label = _("||Please enter the PIN for the standard keys.");
+
+ {
+ char *prompt = make_pin_prompt (app, remaining, label, prkdf);
+ if (!prompt)
+ err = gpg_error_from_syserror ();
+ else
+ err = pincb (pincb_arg, prompt, &pinvalue);
+ xfree (prompt);
+ }
+ if (err)
+ {
+ log_info ("p15: PIN callback returned error: %s\n", gpg_strerror (err));
+ return err;
+ }
+
+ /* We might need to cope with UTF8 things here. Not sure how
+ min_length etc. are exactly defined, for now we take them as
+ a plain octet count. */
+ if (strlen (pinvalue) < aodf->min_length)
+ {
+ log_error ("p15: PIN is too short; minimum length is %lu\n",
+ aodf->min_length);
+ err = gpg_error (GPG_ERR_BAD_PIN);
+ }
+ else if (aodf->stored_length && strlen (pinvalue) > aodf->stored_length)
+ {
+ /* This would otherwise truncate the PIN silently. */
+ log_error ("p15: PIN is too large; maximum length is %lu\n",
+ aodf->stored_length);
+ err = gpg_error (GPG_ERR_BAD_PIN);
+ }
+ else if (aodf->max_length_valid && strlen (pinvalue) > aodf->max_length)
+ {
+ log_error ("p15: PIN is too large; maximum length is %lu\n",
+ aodf->max_length);
+ err = gpg_error (GPG_ERR_BAD_PIN);
+ }
+
+ if (err)
+ {
+ xfree (pinvalue);
+ return err;
+ }
+
+ errstr = NULL;
+ err = 0;
+ switch (aodf->pintype)
+ {
+ case PIN_TYPE_BCD:
+ case PIN_TYPE_ASCII_NUMERIC:
+ for (s=pinvalue; digitp (s); s++)
+ ;
+ if (*s)
+ {
+ errstr = "Non-numeric digits found in PIN";
+ err = gpg_error (GPG_ERR_BAD_PIN);
+ }
+ break;
+ case PIN_TYPE_UTF8:
+ break;
+ case PIN_TYPE_HALF_NIBBLE_BCD:
+ errstr = "PIN type Half-Nibble-BCD is not supported";
+ break;
+ case PIN_TYPE_ISO9564_1:
+ errstr = "PIN type ISO9564-1 is not supported";
+ break;
+ default:
+ errstr = "Unknown PIN type";
+ break;
+ }
+ if (errstr)
+ {
+ log_error ("p15: can't verify PIN: %s\n", errstr);
+ xfree (pinvalue);
+ return err? err : gpg_error (GPG_ERR_BAD_PIN_METHOD);
+ }
+
+
+ if (aodf->pintype == PIN_TYPE_BCD )
+ {
+ char *paddedpin;
+ int ndigits;
+
+ for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
+ ;
+ paddedpin = xtrymalloc (aodf->stored_length+1);
+ if (!paddedpin)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (pinvalue);
+ return err;
+ }
+
+ i = 0;
+ paddedpin[i++] = 0x20 | (ndigits & 0x0f);
+ for (s=pinvalue; i < aodf->stored_length && *s && s[1]; s = s+2 )
+ paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
+ if (i < aodf->stored_length && *s)
+ paddedpin[i++] = (((*s - '0') << 4)
+ |((aodf->pad_char_valid?aodf->pad_char:0)&0x0f));
+
+ if (aodf->pinflags.needs_padding)
+ {
+ while (i < aodf->stored_length)
+ paddedpin[i++] = aodf->pad_char_valid? aodf->pad_char : 0;
+ }
+
+ xfree (pinvalue);
+ pinvalue = paddedpin;
+ pinvaluelen = i;
+ }
+ else if (aodf->pinflags.needs_padding)
+ {
+ char *paddedpin;
+
+ paddedpin = xtrymalloc (aodf->stored_length+1);
+ if (!paddedpin)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (pinvalue);
+ return err;
+ }
+ for (i=0, s=pinvalue; i < aodf->stored_length && *s; i++, s++)
+ paddedpin[i] = *s;
+ /* Not sure what padding char to use if none has been set.
+ For now we use 0x00; maybe a space would be better. */
+ for (; i < aodf->stored_length; i++)
+ paddedpin[i] = aodf->pad_char_valid? aodf->pad_char : 0;
+ paddedpin[i] = 0;
+ pinvaluelen = i;
+ xfree (pinvalue);
+ pinvalue = paddedpin;
+ }
+ else
+ pinvaluelen = strlen (pinvalue);
+
+ /* log_printhex (pinvalue, pinvaluelen, */
+ /* "about to verify with ref %lu pin:", pin_reference); */
+ err = iso7816_verify (app_get_slot (app), pin_reference,
+ pinvalue, pinvaluelen);
+ xfree (pinvalue);
+ if (err)
+ {
+ log_error ("p15: PIN verification failed: %s\n", gpg_strerror (err));
+ return err;
+ }
+ if (opt.verbose)
+ log_info ("p15: PIN verification succeeded\n");
+ prkdf->pin_verified = 1;
+
+ return 0;
+}
+
+
+
+
/* Handler for the PKSIGN command.
Create the signature and return the allocated result in OUTDATA.
@@ -2851,6 +3629,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
const void *indata, size_t indatalen,
unsigned char **outdata, size_t *outdatalen )
{
+ static unsigned char sha256_prefix[19] = /* OID: 2.16.840.1.101.3.4.2.1 */
+ { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
@@ -2859,18 +3640,24 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
gpg_error_t err;
- int i;
- unsigned char data[36]; /* Must be large enough for a SHA-1 digest
- + the largest OID prefix above and also
- fit the 36 bytes of md5sha1. */
+ unsigned char data[32+19]; /* Must be large enough for a SHA-256 digest
+ * + the largest OID prefix above and also
+ * fit the 36 bytes of md5sha1. */
prkdf_object_t prkdf; /* The private key object. */
aodf_object_t aodf; /* The associated authentication object. */
int no_data_padding = 0; /* True if the card want the data without padding.*/
int mse_done = 0; /* Set to true if the MSE has been done. */
+ unsigned int hashlen; /* Length of the hash. */
+ unsigned int datalen; /* Length of the data to sign (prefix+hash). */
+ unsigned char *dataptr;
+ int exmode, le_value;
+
if (!keyidstr || !*keyidstr)
return gpg_error (GPG_ERR_INV_VALUE);
- if (indatalen != 20 && indatalen != 16 && indatalen != 35 && indatalen != 36)
+ if (indatalen != 20 && indatalen != 16
+ && indatalen != 35 && indatalen != 36
+ && indatalen != (32+19))
return gpg_error (GPG_ERR_INV_VALUE);
err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf);
@@ -2879,13 +3666,13 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
if (!(prkdf->usageflags.sign || prkdf->usageflags.sign_recover
||prkdf->usageflags.non_repudiation))
{
- log_error ("key %s may not be used for signing\n", keyidstr);
+ log_error ("p15: key %s may not be used for signing\n", keyidstr);
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
}
if (!prkdf->authid)
{
- log_error ("no authentication object defined for %s\n", keyidstr);
+ log_error ("p15: no authentication object defined for %s\n", keyidstr);
/* fixme: we might want to go ahead and do without PIN
verification. */
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
@@ -2898,37 +3685,25 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
break;
if (!aodf)
{
- log_error ("authentication object for %s missing\n", keyidstr);
- return gpg_error (GPG_ERR_INV_CARD);
- }
- if (aodf->authid)
- {
- log_error ("PIN verification is protected by an "
- "additional authentication token\n");
- return gpg_error (GPG_ERR_BAD_PIN_METHOD);
- }
- if (aodf->pinflags.integrity_protected
- || aodf->pinflags.confidentiality_protected)
- {
- log_error ("PIN verification requires unsupported protection method\n");
- return gpg_error (GPG_ERR_BAD_PIN_METHOD);
- }
- if (!aodf->stored_length && aodf->pinflags.needs_padding)
- {
- log_error ("PIN verification requires padding but no length known\n");
+ log_error ("p15: authentication object for %s missing\n", keyidstr);
return gpg_error (GPG_ERR_INV_CARD);
}
- /* Select the key file. Note that this may change the security
- environment thus we do it before PIN verification. */
- err = select_ef_by_path (app, prkdf->path, prkdf->pathlen);
+ /* We need some more info about the key - get the keygrip to
+ * populate these fields. */
+ err = keygrip_from_prkdf (app, prkdf);
if (err)
{
- log_error ("error selecting file for key %s: %s\n",
- keyidstr, gpg_strerror (errno));
+ log_error ("p15: keygrip_from_prkdf failed: %s\n", gpg_strerror (err));
return err;
}
+ /* Prepare PIN verification. This is split so that we can do
+ * MSE operation for some task after having selected the key file but
+ * before sending the verify APDU. */
+ err = prepare_verify_pin (app, keyidstr, prkdf, aodf);
+ if (err)
+ return err;
/* Due to the fact that the non-repudiation signature on a BELPIC
card requires a verify immediately before the DSO we set the
@@ -2956,162 +3731,16 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
}
if (err)
{
- log_error ("MSE failed: %s\n", gpg_strerror (err));
+ log_error ("p15: MSE failed: %s\n", gpg_strerror (err));
return err;
}
+ /* Now that we have all the information available run the actual PIN
+ * verification.*/
+ err = verify_pin (app, pincb, pincb_arg, prkdf, aodf);
+ if (err)
+ return err;
- /* Now that we have all the information available, prepare and run
- the PIN verification.*/
- if (1)
- {
- char *pinvalue;
- size_t pinvaluelen;
- const char *errstr;
- const char *s;
-
- if (prkdf->usageflags.non_repudiation
- && app->app_local->card_type == CARD_TYPE_BELPIC)
- err = pincb (pincb_arg, "PIN (qualified signature!)", &pinvalue);
- else
- err = pincb (pincb_arg, "PIN", &pinvalue);
- if (err)
- {
- log_info ("PIN callback returned error: %s\n", gpg_strerror (err));
- return err;
- }
-
- /* We might need to cope with UTF8 things here. Not sure how
- min_length etc. are exactly defined, for now we take them as
- a plain octet count. */
-
- if (strlen (pinvalue) < aodf->min_length)
- {
- log_error ("PIN is too short; minimum length is %lu\n",
- aodf->min_length);
- err = gpg_error (GPG_ERR_BAD_PIN);
- }
- else if (aodf->stored_length && strlen (pinvalue) > aodf->stored_length)
- {
- /* This would otherwise truncate the PIN silently. */
- log_error ("PIN is too large; maximum length is %lu\n",
- aodf->stored_length);
- err = gpg_error (GPG_ERR_BAD_PIN);
- }
- else if (aodf->max_length_valid && strlen (pinvalue) > aodf->max_length)
- {
- log_error ("PIN is too large; maximum length is %lu\n",
- aodf->max_length);
- err = gpg_error (GPG_ERR_BAD_PIN);
- }
-
- if (err)
- {
- xfree (pinvalue);
- return err;
- }
-
- errstr = NULL;
- err = 0;
- switch (aodf->pintype)
- {
- case PIN_TYPE_BCD:
- case PIN_TYPE_ASCII_NUMERIC:
- for (s=pinvalue; digitp (s); s++)
- ;
- if (*s)
- {
- errstr = "Non-numeric digits found in PIN";
- err = gpg_error (GPG_ERR_BAD_PIN);
- }
- break;
- case PIN_TYPE_UTF8:
- break;
- case PIN_TYPE_HALF_NIBBLE_BCD:
- errstr = "PIN type Half-Nibble-BCD is not supported";
- break;
- case PIN_TYPE_ISO9564_1:
- errstr = "PIN type ISO9564-1 is not supported";
- break;
- default:
- errstr = "Unknown PIN type";
- break;
- }
- if (errstr)
- {
- log_error ("can't verify PIN: %s\n", errstr);
- xfree (pinvalue);
- return err? err : gpg_error (GPG_ERR_BAD_PIN_METHOD);
- }
-
-
- if (aodf->pintype == PIN_TYPE_BCD )
- {
- char *paddedpin;
- int ndigits;
-
- for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
- ;
- paddedpin = xtrymalloc (aodf->stored_length+1);
- if (!paddedpin)
- {
- err = gpg_error_from_syserror ();
- xfree (pinvalue);
- return err;
- }
-
- i = 0;
- paddedpin[i++] = 0x20 | (ndigits & 0x0f);
- for (s=pinvalue; i < aodf->stored_length && *s && s[1]; s = s+2 )
- paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
- if (i < aodf->stored_length && *s)
- paddedpin[i++] = (((*s - '0') << 4)
- |((aodf->pad_char_valid?aodf->pad_char:0)&0x0f));
-
- if (aodf->pinflags.needs_padding)
- while (i < aodf->stored_length)
- paddedpin[i++] = aodf->pad_char_valid? aodf->pad_char : 0;
-
- xfree (pinvalue);
- pinvalue = paddedpin;
- pinvaluelen = i;
- }
- else if (aodf->pinflags.needs_padding)
- {
- char *paddedpin;
-
- paddedpin = xtrymalloc (aodf->stored_length+1);
- if (!paddedpin)
- {
- err = gpg_error_from_syserror ();
- xfree (pinvalue);
- return err;
- }
- for (i=0, s=pinvalue; i < aodf->stored_length && *s; i++, s++)
- paddedpin[i] = *s;
- /* Not sure what padding char to use if none has been set.
- For now we use 0x00; maybe a space would be better. */
- for (; i < aodf->stored_length; i++)
- paddedpin[i] = aodf->pad_char_valid? aodf->pad_char : 0;
- paddedpin[i] = 0;
- pinvaluelen = i;
- xfree (pinvalue);
- pinvalue = paddedpin;
- }
- else
- pinvaluelen = strlen (pinvalue);
-
- err = iso7816_verify (app->slot,
- aodf->pin_reference_valid? aodf->pin_reference : 0,
- pinvalue, pinvaluelen);
- xfree (pinvalue);
- if (err)
- {
- log_error ("PIN verification failed: %s\n", gpg_strerror (err));
- return err;
- }
- log_debug ("PIN verification succeeded\n");
- }
/* Prepare the DER object from INDATA. */
if (indatalen == 36)
@@ -3120,6 +3749,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
if (hashalgo != MD_USER_TLS_MD5SHA1)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
memcpy (data, indata, indatalen);
+ datalen = hashlen = 36;
}
else if (indatalen == 35)
{
@@ -3134,20 +3764,50 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
else
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
memcpy (data, indata, indatalen);
+ datalen = 35;
+ hashlen = 20;
+ }
+ else if (indatalen == 32 + 19)
+ {
+ /* Seems to be a prepared SHA256 DER object. */
+ if (hashalgo == GCRY_MD_SHA256 && !memcmp (indata, sha256_prefix, 19))
+ ;
+ else
+ return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+ memcpy (data, indata, indatalen);
+ datalen = 51;
+ hashlen = 32;
}
else
{
/* Need to prepend the prefix. */
- if (hashalgo == GCRY_MD_SHA1)
- memcpy (data, sha1_prefix, 15);
+ if (hashalgo == GCRY_MD_SHA256)
+ {
+ memcpy (data, sha256_prefix, 19);
+ memcpy (data+19, indata, indatalen);
+ datalen = 51;
+ hashlen = 32;
+ }
+ else if (hashalgo == GCRY_MD_SHA1)
+ {
+ memcpy (data, sha1_prefix, 15);
+ memcpy (data+15, indata, indatalen);
+ datalen = 35;
+ hashlen = 20;
+ }
else if (hashalgo == GCRY_MD_RMD160)
- memcpy (data, rmd160_prefix, 15);
+ {
+ memcpy (data, rmd160_prefix, 15);
+ memcpy (data+15, indata, indatalen);
+ datalen = 35;
+ hashlen = 20;
+ }
else
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- memcpy (data+15, indata, indatalen);
}
- /* Manage security environment needs to be weaked for certain cards. */
+
+ /* Manage security environment needs to be tweaked for certain cards. */
if (mse_done)
err = 0;
else if (app->app_local->card_type == CARD_TYPE_TCOS)
@@ -3176,16 +3836,32 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
}
if (err)
{
- log_error ("MSE failed: %s\n", gpg_strerror (err));
+ log_error ("p15: MSE failed: %s\n", gpg_strerror (err));
return err;
}
- if (hashalgo == MD_USER_TLS_MD5SHA1)
- err = iso7816_compute_ds (app->slot, 0, data, 36, 0, outdata, outdatalen);
- else if (no_data_padding)
- err = iso7816_compute_ds (app->slot, 0, data+15, 20, 0,outdata,outdatalen);
+ dataptr = data;
+ if (no_data_padding)
+ {
+ dataptr += datalen - hashlen;
+ datalen = hashlen;
+ }
+
+ if (prkdf->keyalgo == GCRY_PK_RSA && prkdf->keynbits > 2048)
+ {
+ exmode = 1;
+ le_value = prkdf->keynbits / 8;
+ }
else
- err = iso7816_compute_ds (app->slot, 0, data, 35, 0, outdata, outdatalen);
+ {
+ exmode = 0;
+ le_value = 0;
+ }
+
+ err = iso7816_compute_ds (app_get_slot (app),
+ exmode, dataptr, datalen,
+ le_value, outdata, outdatalen);
+
return err;
}
@@ -3215,7 +3891,7 @@ do_auth (app_t app, const char *keyidstr,
return err;
if (!prkdf->usageflags.sign)
{
- log_error ("key %s may not be used for authentication\n", keyidstr);
+ log_error ("p15: key %s may not be used for authentication\n", keyidstr);
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
}
@@ -3225,6 +3901,134 @@ do_auth (app_t app, const char *keyidstr,
}
+/* Handler for the PKDECRYPT command. Decrypt the data in INDATA and
+ * return the allocated result in OUTDATA. If a PIN is required the
+ * PINCB will be used to ask for the PIN; it should return the PIN in
+ * an allocated buffer and put it into PIN. */
+static gpg_error_t
+do_decipher (app_t app, const char *keyidstr,
+ gpg_error_t (*pincb)(void*, const char *, char **),
+ void *pincb_arg,
+ const void *indata, size_t indatalen,
+ unsigned char **outdata, size_t *outdatalen,
+ unsigned int *r_info)
+{
+ gpg_error_t err;
+ prkdf_object_t prkdf; /* The private key object. */
+ aodf_object_t aodf; /* The associated authentication object. */
+ int exmode, le_value, padind;
+
+ (void)r_info;
+
+ if (!keyidstr || !*keyidstr)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!indatalen || !indata || !outdatalen || !outdata)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf);
+ if (err)
+ return err;
+ if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap))
+ {
+ log_error ("p15: key %s may not be used for decruption\n", keyidstr);
+ return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
+ }
+
+ /* Find the authentication object to this private key object. */
+ if (!prkdf->authid)
+ {
+ log_error ("p15: no authentication object defined for %s\n", keyidstr);
+ /* fixme: we might want to go ahead and do without PIN
+ verification. */
+ return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
+ }
+ for (aodf = app->app_local->auth_object_info; aodf; aodf = aodf->next)
+ if (aodf->objidlen == prkdf->authidlen
+ && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen))
+ break;
+ if (!aodf)
+ {
+ log_error ("p15: authentication object for %s missing\n", keyidstr);
+ return gpg_error (GPG_ERR_INV_CARD);
+ }
+
+ /* We need some more info about the key - get the keygrip to
+ * populate these fields. */
+ err = keygrip_from_prkdf (app, prkdf);
+ if (err)
+ {
+ log_error ("p15: keygrip_from_prkdf failed: %s\n", gpg_strerror (err));
+ return err;
+ }
+
+ /* Verify the PIN. */
+ err = prepare_verify_pin (app, keyidstr, prkdf, aodf);
+ if (!err)
+ err = verify_pin (app, pincb, pincb_arg, prkdf, aodf);
+ if (err)
+ return err;
+
+
+ /* The next is guess work for CardOS. */
+ if (app->app_local->card_product == CARD_PRODUCT_DTRUST)
+ {
+ /* From analyzing an USB trace of a Windows signing application
+ * we see that the SE is simply reset to 0x14. It seems to be
+ * sufficient to do this for decryption; signing still works
+ * with the standard code despite that our trace showed that
+ * there the SE is restored to 0x09. Note that the special
+ * D-Trust AID is in any case select by prepare_verify_pin.
+ *
+ * Hey, D-Trust please hand over the specs so that you can
+ * actually sell your cards and we can properly implement it;
+ * other vendors understand this and do not demand ridiculous
+ * paper work or complicated procedures to get samples. */
+ err = iso7816_manage_security_env (app_get_slot (app),
+ 0xF3, 0x14, NULL, 0);
+
+ }
+ else if (prkdf->key_reference_valid)
+ {
+ unsigned char mse[6];
+
+ /* Note: This works with CardOS but the D-Trust card has the
+ * problem that the next created signature would be broken. */
+
+ mse[0] = 0x80; /* Algorithm reference. */
+ mse[1] = 1;
+ mse[2] = 0x0a; /* RSA, no padding. */
+ mse[3] = 0x84;
+ mse[4] = 1;
+ mse[5] = prkdf->key_reference;
+ err = iso7816_manage_security_env (app_get_slot (app), 0x41, 0xB8,
+ mse, sizeof mse);
+ }
+ /* Check for MSE error. */
+ if (err)
+ {
+ log_error ("p15: MSE failed: %s\n", gpg_strerror (err));
+ return err;
+ }
+
+ exmode = le_value = 0;
+ padind = 0;
+ if (prkdf->keyalgo == GCRY_PK_RSA && prkdf->keynbits > 2048)
+ {
+ exmode = 1; /* Extended length w/o a limit. */
+ le_value = prkdf->keynbits / 8;
+ }
+
+ if (app->app_local->card_product == CARD_PRODUCT_DTRUST)
+ padind = 0x81;
+
+ err = iso7816_decipher (app_get_slot (app), exmode,
+ indata, indatalen,
+ le_value, padind,
+ outdata, outdatalen);
+ return err;
+}
+
+
/* Assume that EF(DIR) has been selected. Read its content and figure
out the home EF of pkcs#15. Return that home DF or 0 if not found
@@ -3244,7 +4048,7 @@ read_home_df (int slot, int *r_belpic)
err = iso7816_read_binary (slot, 0, 0, &buffer, &buflen);
if (err)
{
- log_error ("error reading EF{DIR}: %s\n", gpg_strerror (err));
+ log_error ("p15: error reading EF(DIR): %s\n", gpg_strerror (err));
return 0;
}
@@ -3258,14 +4062,15 @@ read_home_df (int slot, int *r_belpic)
&& !memcmp (pp, pkcs15be_aid, nn)))))
{
pp = find_tlv (p, n, 0x50, &nn);
- if (pp) /* fixme: Filter log value? */
- log_info ("pkcs#15 application label from EF(DIR) is '%.*s'\n",
+ if (pp && opt.verbose)
+ log_info ("p15: application label from EF(DIR) is '%.*s'\n",
(int)nn, pp);
pp = find_tlv (p, n, 0x51, &nn);
if (pp && nn == 4 && *pp == 0x3f && !pp[1])
{
result = ((pp[2] << 8) | pp[3]);
- log_info ("pkcs#15 application directory is 0x%04hX\n", result);
+ if (opt.verbose)
+ log_info ("p15: application directory is 0x%04hX\n", result);
}
}
}
@@ -3294,11 +4099,11 @@ app_select_p15 (app_t app)
does only allow for that. Many other cards supports this
selection method too. Note, that we don't use
select_application above for the Belgian card - the call
- works but it seems that it did not switch to the correct DF.
+ works but it seems that it does not switch to the correct DF.
Using the 2f02 just works. */
unsigned short path[1] = { 0x2f00 };
- rc = iso7816_select_path (app->slot, path, 1);
+ rc = iso7816_select_path (slot, path, 1);
if (!rc)
{
direct = 1;
@@ -3306,7 +4111,7 @@ app_select_p15 (app_t app)
if (def_home_df)
{
path[0] = def_home_df;
- rc = iso7816_select_path (app->slot, path, 1);
+ rc = iso7816_select_path (slot, path, 1);
}
}
}
@@ -3368,6 +4173,8 @@ app_select_p15 (app_t app)
the common APP structure. */
app->app_local->card_type = card_type;
+ app->app_local->card_product = CARD_PRODUCT_UNKNOWN;
+
/* Store whether we may and should use direct path selection. */
app->app_local->direct_path_selection = direct;
@@ -3411,7 +4218,7 @@ app_select_p15 (app_t app)
app->fnc.genkey = NULL;
app->fnc.sign = do_sign;
app->fnc.auth = do_auth;
- app->fnc.decipher = NULL;
+ app->fnc.decipher = do_decipher;
app->fnc.change_pin = NULL;
app->fnc.check_pin = NULL;
diff --git a/scd/app-sc-hsm.c b/scd/app-sc-hsm.c
index 8094b24..352b16c 100644
--- a/scd/app-sc-hsm.c
+++ b/scd/app-sc-hsm.c
@@ -1354,7 +1354,7 @@ keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr)
err = ksba_cert_init_from_mem (cert, der, derlen);
xfree (der);
if (!err)
- err = app_help_get_keygrip_string (cert, r_gripstr);
+ err = app_help_get_keygrip_string (cert, r_gripstr, NULL);
ksba_cert_release (cert);
return err;
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 627481f..092a119 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -103,6 +103,8 @@ map_sw (int sw)
ec = GPG_ERR_GENERAL; /* Should not happen. */
else if ((sw & 0xff00) == SW_MORE_DATA)
ec = 0; /* This should actually never been seen here. */
+ else if ((sw & 0xfff0) == 0x63C0)
+ ec = GPG_ERR_BAD_PIN;
else
ec = GPG_ERR_CARD;
}
@@ -139,6 +141,32 @@ iso7816_select_application (int slot, const char *aid, size_t aidlen,
}
+/* This is the same as iso7816_select_application but may return data
+ * at RESULT,RESULTLEN). */
+gpg_error_t
+iso7816_select_application_ext (int slot, const char *aid, size_t aidlen,
+ unsigned int flags,
+ unsigned char **result, size_t *resultlen)
+{
+ int sw;
+ sw = apdu_send (slot, 0, 0x00, CMD_SELECT_FILE, 4,
+ (flags&1)? 0:0x0c, aidlen, aid,
+ result, resultlen);
+ return map_sw (sw);
+}
+
+
+/* Simple MF selection as supported by some cards. */
+gpg_error_t
+iso7816_select_mf (int slot)
+{
+ int sw;
+
+ sw = apdu_send_simple (slot, 0, 0x00, CMD_SELECT_FILE, 0x000, 0x0c, -1, NULL);
+ return map_sw (sw);
+}
+
+
gpg_error_t
iso7816_select_file (int slot, int tag, int is_dir)
{
@@ -289,6 +317,39 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
return map_sw (sw);
}
+
+/* Some cards support a VERIFY command variant to check the status of
+ * the the CHV without a need to try a CHV. In contrast to the other
+ * functions this function returns the special codes ISO7816_VERIFY_*
+ * or a non-negative number with the left attempts. */
+int
+iso7816_verify_status (int slot, int chvno)
+{
+ unsigned char apdu[4];
+ unsigned int sw;
+ int result;
+
+ apdu[0] = 0x00;
+ apdu[1] = ISO7816_VERIFY;
+ apdu[2] = 0x00;
+ apdu[3] = chvno;
+ if (!iso7816_apdu_direct (slot, apdu, 4, 0, &sw, NULL, NULL))
+ result = ISO7816_VERIFY_NOT_NEEDED; /* Not returned by all cards. */
+ else if (sw == 0x6a88 || sw == 0x6a80)
+ result = ISO7816_VERIFY_NO_PIN;
+ else if (sw == 0x6983)
+ result = ISO7816_VERIFY_BLOCKED;
+ else if (sw == 0x6985)
+ result = ISO7816_VERIFY_NULLPIN; /* TCOS card */
+ else if ((sw & 0xfff0) == 0x63C0)
+ result = (sw & 0x000f);
+ else
+ result = ISO7816_VERIFY_ERROR;
+
+ return result;
+}
+
+
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
verification vector CHVNO. With PININFO non-NULL the pinpad of the
reader will be used. If IS_EXCHANGE is 0, a "change reference
@@ -722,8 +783,9 @@ iso7816_get_challenge (int slot, int length, unsigned char *buffer)
stored in a newly allocated buffer at the address passed by RESULT.
Returns the length of this data at the address of RESULTLEN. */
gpg_error_t
-iso7816_read_binary (int slot, size_t offset, size_t nmax,
- unsigned char **result, size_t *resultlen)
+iso7816_read_binary_ext (int slot, int extended_mode,
+ size_t offset, size_t nmax,
+ unsigned char **result, size_t *resultlen)
{
int sw;
unsigned char *buffer;
@@ -746,13 +808,13 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax,
buffer = NULL;
bufferlen = 0;
n = read_all? 0 : nmax;
- sw = apdu_send_le (slot, 0, 0x00, CMD_READ_BINARY,
+ sw = apdu_send_le (slot, extended_mode, 0x00, CMD_READ_BINARY,
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
n, &buffer, &bufferlen);
if ( SW_EXACT_LENGTH_P(sw) )
{
n = (sw & 0x00ff);
- sw = apdu_send_le (slot, 0, 0x00, CMD_READ_BINARY,
+ sw = apdu_send_le (slot, extended_mode, 0x00, CMD_READ_BINARY,
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
n, &buffer, &bufferlen);
}
@@ -811,6 +873,15 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax,
return 0;
}
+
+gpg_error_t
+iso7816_read_binary (int slot, size_t offset, size_t nmax,
+ unsigned char **result, size_t *resultlen)
+{
+ return iso7816_read_binary_ext (slot, 0, offset, nmax, result, resultlen);
+}
+
+
/* Perform a READ RECORD command. RECNO gives the record number to
read with 0 indicating the current record. RECCOUNT must be 1 (not
all cards support reading of more than one record). SHORT_EF
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 8da5a94..bad558d 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -29,6 +29,15 @@
#define ISO7816_CHANGE_REFERENCE_DATA 0x24
#define ISO7816_RESET_RETRY_COUNTER 0x2C
+/* Error codes returned by iso7816_verify_status. A non-negative
+ * number gives the number of left tries.
+ * NB: The values are also used by the CHV-STATUS lines and thus are
+ * part of the public interface. Do not change them. */
+#define ISO7816_VERIFY_ERROR (-1)
+#define ISO7816_VERIFY_NO_PIN (-2)
+#define ISO7816_VERIFY_BLOCKED (-3)
+#define ISO7816_VERIFY_NULLPIN (-4)
+#define ISO7816_VERIFY_NOT_NEEDED (-5)
/* Information to be passed to pinpad equipped readers. See
ccid-driver.c for details. */
@@ -51,6 +60,12 @@ gpg_error_t iso7816_map_sw (int sw);
gpg_error_t iso7816_select_application (int slot,
const char *aid, size_t aidlen,
unsigned int flags);
+gpg_error_t iso7816_select_application_ext (int slot,
+ const char *aid, size_t aidlen,
+ unsigned int flags,
+ unsigned char **result,
+ size_t *resultlen);
+gpg_error_t iso7816_select_mf (int slot);
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir);
gpg_error_t iso7816_select_path (int slot,
const unsigned short *path, size_t pathlen);
@@ -65,6 +80,7 @@ gpg_error_t iso7816_check_pinpad (int slot, int command,
gpg_error_t iso7816_verify (int slot,
int chvno, const char *chv, size_t chvlen);
gpg_error_t iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo);
+int iso7816_verify_status (int slot, int chvno);
gpg_error_t iso7816_change_reference_data (int slot, int chvno,
const char *oldchv, size_t oldchvlen,
const char *newchv, size_t newchvlen);
@@ -117,6 +133,9 @@ gpg_error_t iso7816_read_public_key (int slot, int extended_mode,
gpg_error_t iso7816_get_challenge (int slot,
int length, unsigned char *buffer);
+gpg_error_t iso7816_read_binary_ext (int slot, int extended_mode,
+ size_t offset, size_t nmax,
+ unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_read_binary (int slot, size_t offset, size_t nmax,
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_read_record (int slot, int recno, int reccount,
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 281e479..d9c419e 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -1248,7 +1248,7 @@ gpgsm_agent_ask_passphrase (ctrl_t ctrl, const char *desc_msg, int repeat,
return gpg_error_from_syserror ();
snprintf (line, DIM(line), "GET_PASSPHRASE --data%s -- X X X %s",
- repeat? " --repeat=1 --check --qualitybar":"",
+ repeat? " --repeat=1 --check":"",
arg4);
xfree (arg4);
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index fb05413..36afd22 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -756,20 +756,24 @@ lookup_status_cb (void *opaque, const char *line)
/* Run the Directory Manager's lookup command using the pattern
- compiled from the strings given in NAMES. The caller must provide
- the callback CB which will be passed cert by cert. Note that CTRL
- is optional. With CACHE_ONLY the dirmngr will search only its own
- key cache. */
+ compiled from the strings given in NAMES or from URI. The caller
+ must provide the callback CB which will be passed cert by cert.
+ Note that CTRL is optional. With CACHE_ONLY the dirmngr will
+ search only its own key cache. */
int
-gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
+gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, const char *uri,
+ int cache_only,
void (*cb)(void*, ksba_cert_t), void *cb_value)
{
int rc;
- char *pattern;
char line[ASSUAN_LINELENGTH];
struct lookup_parm_s parm;
size_t len;
assuan_context_t ctx;
+ const char *s;
+
+ if ((names && uri) || (!names && !uri))
+ return gpg_error (GPG_ERR_INV_ARG);
/* The lookup function can be invoked from the callback of a lookup
function, for example to walk the chain. */
@@ -792,19 +796,35 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
log_fatal ("both dirmngr contexts are in use\n");
}
- pattern = pattern_from_strlist (names);
- if (!pattern)
+ if (names)
{
- if (ctx == dirmngr_ctx)
- release_dirmngr (ctrl);
- else
- release_dirmngr2 (ctrl);
+ char *pattern = pattern_from_strlist (names);
+ if (!pattern)
+ {
+ if (ctx == dirmngr_ctx)
+ release_dirmngr (ctrl);
+ else
+ release_dirmngr2 (ctrl);
- return out_of_core ();
+ return out_of_core ();
+ }
+ snprintf (line, DIM(line), "LOOKUP%s %s",
+ cache_only? " --cache-only":"", pattern);
+ xfree (pattern);
+ }
+ else
+ {
+ for (s=uri; *s; s++)
+ if (*s <= ' ')
+ {
+ if (ctx == dirmngr_ctx)
+ release_dirmngr (ctrl);
+ else
+ release_dirmngr2 (ctrl);
+ return gpg_error (GPG_ERR_INV_URI);
+ }
+ snprintf (line, DIM(line), "LOOKUP --url %s", uri);
}
- snprintf (line, DIM(line), "LOOKUP%s %s",
- cache_only? " --cache-only":"", pattern);
- xfree (pattern);
parm.ctrl = ctrl;
parm.ctx = ctx;
diff --git a/sm/certchain.c b/sm/certchain.c
index f59dc75..5f83202 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -38,6 +38,10 @@
#include "../common/tlv.h"
+/* The OID for the authorityInfoAccess's caIssuers. */
+static const char oidstr_caIssuers[] = "1.3.6.1.5.5.7.48.2";
+
+
/* Object to keep track of certain root certificates. */
struct marktrusted_info_s
{
@@ -573,6 +577,9 @@ struct find_up_store_certs_s
{
ctrl_t ctrl;
int count;
+ unsigned int want_fpr:1;
+ unsigned int got_fpr:1;
+ unsigned char fpr[20];
};
static void
@@ -582,6 +589,13 @@ find_up_store_certs_cb (void *cb_value, ksba_cert_t cert)
if (keydb_store_cert (parm->ctrl, cert, 1, NULL))
log_error ("error storing issuer certificate as ephemeral\n");
+ else if (parm->want_fpr && !parm->got_fpr)
+ {
+ if (!gpgsm_get_fingerprint (cert, 0, parm->fpr, NULL))
+ log_error (_("failed to get the fingerprint\n"));
+ else
+ parm->got_fpr = 1;
+ }
parm->count++;
}
@@ -602,6 +616,8 @@ find_up_external (ctrl_t ctrl, KEYDB_HANDLE kh,
const char *s;
find_up_store_certs_parm.ctrl = ctrl;
+ find_up_store_certs_parm.want_fpr = 0;
+ find_up_store_certs_parm.got_fpr = 0;
find_up_store_certs_parm.count = 0;
if (opt.verbose)
@@ -620,7 +636,7 @@ find_up_external (ctrl_t ctrl, KEYDB_HANDLE kh,
add_to_strlist (&names, pattern);
xfree (pattern);
- rc = gpgsm_dirmngr_lookup (ctrl, names, 0, find_up_store_certs_cb,
+ rc = gpgsm_dirmngr_lookup (ctrl, names, NULL, 0, find_up_store_certs_cb,
&find_up_store_certs_parm);
free_strlist (names);
@@ -653,6 +669,105 @@ find_up_external (ctrl_t ctrl, KEYDB_HANDLE kh,
}
+/* Helper for find_up(). Locate the certificate for CERT using the
+ * caIssuer from the authorityInfoAccess. KH is the keydb context we
+ * are currently using. On success 0 is returned and the certificate
+ * may be retrieved from the keydb using keydb_get_cert(). If no
+ * suitable authorityInfoAccess is encoded in the certificate
+ * GPG_ERR_NOT_FOUND is returned. */
+static gpg_error_t
+find_up_via_auth_info_access (ctrl_t ctrl, KEYDB_HANDLE kh, ksba_cert_t cert)
+{
+ gpg_error_t err;
+ struct find_up_store_certs_s find_up_store_certs_parm;
+ char *url, *ldapurl;
+ int idx, i;
+ char *oid;
+ ksba_name_t name;
+
+ find_up_store_certs_parm.ctrl = ctrl;
+ find_up_store_certs_parm.want_fpr = 1;
+ find_up_store_certs_parm.got_fpr = 0;
+ find_up_store_certs_parm.count = 0;
+
+ /* Find suitable URLs; if there is a http scheme we prefer that. */
+ url = ldapurl = NULL;
+ for (idx=0;
+ !url && !(err = ksba_cert_get_authority_info_access (cert, idx,
+ &oid, &name));
+ idx++)
+ {
+ if (!strcmp (oid, oidstr_caIssuers))
+ {
+ for (i=0; !url && ksba_name_enum (name, i); i++)
+ {
+ char *p = ksba_name_get_uri (name, i);
+ if (p)
+ {
+ if (!strncmp (p, "http:", 5) || !strncmp (p, "https:", 6))
+ url = p;
+ else if (ldapurl)
+ xfree (p); /* We already got one. */
+ else if (!strncmp (p, "ldap:",5) || !strncmp (p, "ldaps:",6))
+ ldapurl = p;
+ }
+ else
+ xfree (p);
+ }
+ }
+ ksba_name_release (name);
+ ksba_free (oid);
+ }
+ if (err && gpg_err_code (err) != GPG_ERR_EOF)
+ {
+ log_error (_("can't get authorityInfoAccess: %s\n"), gpg_strerror (err));
+ return err;
+ }
+ if (!url && ldapurl)
+ {
+ /* No HTTP scheme; fallback to LDAP if available. */
+ url = ldapurl;
+ ldapurl = NULL;
+ }
+ xfree (ldapurl);
+ if (!url)
+ return gpg_error (GPG_ERR_NOT_FOUND);
+
+ if (opt.verbose)
+ log_info ("looking up issuer via authorityInfoAccess.caIssuers\n");
+
+ err = gpgsm_dirmngr_lookup (ctrl, NULL, url, 0, find_up_store_certs_cb,
+ &find_up_store_certs_parm);
+
+ /* Although we might receive several certificates we use only the
+ * first one. Or more exacty the first one for which we retrieved
+ * the fingerprint. */
+ if (opt.verbose)
+ log_info ("number of caIssuers found: %d\n",
+ find_up_store_certs_parm.count);
+ if (err)
+ {
+ log_error ("external URL lookup failed: %s\n", gpg_strerror (err));
+ err = gpg_error (GPG_ERR_NOT_FOUND);
+ }
+ else if (!find_up_store_certs_parm.got_fpr)
+ err = gpg_error (GPG_ERR_NOT_FOUND);
+ else
+ {
+ int old;
+ /* The retrieved certificates are currently stored in the
+ * ephemeral key DB, so we temporary switch to ephemeral
+ * mode. */
+ old = keydb_set_ephemeral (kh, 1);
+ keydb_search_reset (kh);
+ err = keydb_search_fpr (ctrl, kh, find_up_store_certs_parm.fpr);
+ keydb_set_ephemeral (kh, old);
+ }
+
+ return err;
+}
+
+
/* Helper for find_up(). Ask the dirmngr for the certificate for
ISSUER with optional SERIALNO. KH is the keydb context we are
currently using. With SUBJECT_MODE set, ISSUER is searched as the
@@ -693,7 +808,7 @@ find_up_dirmngr (ctrl_t ctrl, KEYDB_HANDLE kh,
add_to_strlist (&names, pattern);
xfree (pattern);
- rc = gpgsm_dirmngr_lookup (ctrl, names, 1, find_up_store_certs_cb,
+ rc = gpgsm_dirmngr_lookup (ctrl, names, NULL, 1, find_up_store_certs_cb,
&find_up_store_certs_parm);
free_strlist (names);
@@ -813,11 +928,24 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
}
/* If we still didn't found it, try an external lookup. */
- if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
+ if (rc == -1 && !find_next && !ctrl->offline)
{
- rc = find_up_external (ctrl, kh, issuer, keyid);
- if (!rc && DBG_X509)
- log_debug (" found via authid and external lookup\n");
+ /* We allow AIA also if CRLs are enabled; both can be used
+ * as a web bug so it does not make sense to not use AIA if
+ * CRL checks are enabled. */
+ if ((opt.auto_issuer_key_retrieve || !opt.no_crl_check)
+ && !find_up_via_auth_info_access (ctrl, kh, cert))
+ {
+ if (DBG_X509)
+ log_debug (" found via authorityInfoAccess.caIssuers\n");
+ rc = 0;
+ }
+ else if (opt.auto_issuer_key_retrieve)
+ {
+ rc = find_up_external (ctrl, kh, issuer, keyid);
+ if (!rc && DBG_X509)
+ log_debug (" found via authid and external lookup\n");
+ }
}
@@ -876,11 +1004,21 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
}
/* Still not found. If enabled, try an external lookup. */
- if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
+ if (rc == -1 && !find_next && !ctrl->offline)
{
- rc = find_up_external (ctrl, kh, issuer, NULL);
- if (!rc && DBG_X509)
- log_debug (" found via issuer and external lookup\n");
+ if ((opt.auto_issuer_key_retrieve || !opt.no_crl_check)
+ && !find_up_via_auth_info_access (ctrl, kh, cert))
+ {
+ if (DBG_X509)
+ log_debug (" found via authorityInfoAccess.caIssuers\n");
+ rc = 0;
+ }
+ else if (opt.auto_issuer_key_retrieve)
+ {
+ rc = find_up_external (ctrl, kh, issuer, NULL);
+ if (!rc && DBG_X509)
+ log_debug (" found via issuer and external lookup\n");
+ }
}
return rc;
@@ -1054,6 +1192,24 @@ is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp,
return 0;
}
+
+ if (!(force_ocsp || ctrl->use_ocsp)
+ && !opt.enable_issuer_based_crl_check)
+ {
+ err = ksba_cert_get_crl_dist_point (subject_cert, 0, NULL, NULL, NULL);
+ if (gpg_err_code (err) == GPG_ERR_EOF)
+ {
+ /* No DP specified in the certificate. Thus the CA does not
+ * consider a CRL useful and the user of the certificate
+ * also does not consider this to be a critical thing. In
+ * this case we can conclude that the certificate shall not
+ * be revocable. Note that we reach this point here only if
+ * no OCSP responder shall be used. */
+ audit_log_ok (ctrl->audit, AUDIT_CRL_CHECK, gpg_error (GPG_ERR_TRUE));
+ return 0;
+ }
+ }
+
err = gpgsm_dirmngr_isvalid (ctrl,
subject_cert, issuer_cert,
force_ocsp? 2 : !!ctrl->use_ocsp);
diff --git a/sm/certcheck.c b/sm/certcheck.c
index 1102bcc..12b3ec9 100644
--- a/sm/certcheck.c
+++ b/sm/certcheck.c
@@ -1,5 +1,7 @@
/* certcheck.c - check one certificate
- * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2001-2019 Werner Koch
+ * Copyright (C) 2015-2020 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -15,6 +17,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <config.h>
@@ -220,6 +223,126 @@ pk_algo_from_sexp (gcry_sexp_t pkey)
}
+/* Return the hash algorithm's algo id from its name given in the
+ * non-null termnated string in (buffer,buflen). Returns 0 on failure
+ * or if the algo is not known. */
+static int
+hash_algo_from_buffer (const void *buffer, size_t buflen)
+{
+ char *string;
+ int algo;
+
+ string = xtrymalloc (buflen + 1);
+ if (!string)
+ {
+ log_error (_("out of core\n"));
+ return 0;
+ }
+ memcpy (string, buffer, buflen);
+ string[buflen] = 0;
+ algo = gcry_md_map_name (string);
+ if (!algo)
+ log_error ("unknown digest algorithm '%s' used in certificate\n", string);
+ xfree (string);
+ return algo;
+}
+
+
+/* Return an unsigned integer from the non-null termnated string
+ * (buffer,buflen). Returns 0 on failure. */
+static unsigned int
+uint_from_buffer (const void *buffer, size_t buflen)
+{
+ char *string;
+ unsigned int val;
+
+ string = xtrymalloc (buflen + 1);
+ if (!string)
+ {
+ log_error (_("out of core\n"));
+ return 0;
+ }
+ memcpy (string, buffer, buflen);
+ string[buflen] = 0;
+ val = strtoul (string, NULL, 10);
+ xfree (string);
+ return val;
+}
+
+
+/* Extract the hash algorithm and the salt length from the sigval. */
+static gpg_error_t
+extract_pss_params (gcry_sexp_t s_sig, int *r_algo, unsigned int *r_saltlen)
+{
+ gpg_error_t err;
+ gcry_buffer_t ioarray[2] = { {0}, {0} };
+
+ err = gcry_sexp_extract_param (s_sig, "sig-val",
+ "&'hash-algo''salt-length'",
+ ioarray+0, ioarray+1, NULL);
+ if (err)
+ {
+ log_error ("extracting params from PSS failed: %s\n", gpg_strerror (err));
+ return err;
+ }
+
+ *r_algo = hash_algo_from_buffer (ioarray[0].data, ioarray[0].len);
+ *r_saltlen = uint_from_buffer (ioarray[1].data, ioarray[1].len);
+ xfree (ioarray[0].data);
+ xfree (ioarray[1].data);
+ if (*r_saltlen < 20)
+ {
+ log_error ("length of PSS salt too short\n");
+ gcry_sexp_release (s_sig);
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+ if (!*r_algo)
+ {
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+
+ /* PSS has no hash function firewall like PKCS#1 and thus offers
+ * a path for hash algorithm replacement. To avoid this it makes
+ * sense to restrict the allowed hash algorithms and also allow only
+ * matching salt lengths. According to Peter Gutmann:
+ * "Beware of bugs in the above signature scheme;
+ * I have only proved it secure, not implemented it"
+ * - Apologies to Donald Knuth.
+ * https://www.metzdowd.com/pipermail/cryptography/2019-November/035449.html
+ *
+ * Given the set of supported algorithms currently available in
+ * Libgcrypt and the extra hash checks we have in some compliance
+ * modes, it would be hard to trick gpgsm to verify a forged
+ * signature. However, if eventually someone adds the xor256 hash
+ * algorithm (1.3.6.1.4.1.3029.3.2) to Libgcrypt we would be doomed.
+ */
+ switch (*r_algo)
+ {
+ case GCRY_MD_SHA1:
+ case GCRY_MD_SHA256:
+ case GCRY_MD_SHA384:
+ case GCRY_MD_SHA512:
+ case GCRY_MD_SHA3_256:
+ case GCRY_MD_SHA3_384:
+ case GCRY_MD_SHA3_512:
+ break;
+ default:
+ log_error ("PSS hash algorithm '%s' rejected\n",
+ gcry_md_algo_name (*r_algo));
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+
+ if (gcry_md_get_algo_dlen (*r_algo) != *r_saltlen)
+ {
+ log_error ("PSS hash algorithm '%s' rejected due to salt length %u\n",
+ gcry_md_algo_name (*r_algo), *r_saltlen);
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+
+ return 0;
+}
+
+
/* Check the signature on CERT using the ISSUER-CERT. This function
does only test the cryptographic signature and nothing else. It is
assumed that the ISSUER_CERT is valid. */
@@ -229,66 +352,76 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
const char *algoid;
gcry_md_hd_t md;
int rc, algo;
- gcry_mpi_t frame;
ksba_sexp_t p;
size_t n;
- gcry_sexp_t s_sig, s_hash, s_pkey;
+ gcry_sexp_t s_sig, s_data, s_pkey;
+ int use_pss = 0;
+ unsigned int saltlen;
algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert)));
- if (!algo)
+ if (!algo && algoid && !strcmp (algoid, "1.2.840.113549.1.1.10"))
+ use_pss = 1;
+ else if (!algo)
{
- log_error ("unknown hash algorithm '%s'\n", algoid? algoid:"?");
+ log_error ("unknown digest algorithm '%s' used certificate\n",
+ algoid? algoid:"?");
if (algoid
&& ( !strcmp (algoid, "1.2.840.113549.1.1.2")
||!strcmp (algoid, "1.2.840.113549.2.2")))
log_info (_("(this is the MD2 algorithm)\n"));
return gpg_error (GPG_ERR_GENERAL);
}
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- return rc;
- }
- if (DBG_HASHING)
- gcry_md_debug (md, "hash.cert");
-
- rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
- if (rc)
- {
- log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- return rc;
- }
- gcry_md_final (md);
+ /* The the signature from the certificate. */
p = ksba_cert_get_sig_val (cert);
n = gcry_sexp_canon_len (p, 0, NULL, NULL);
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
- gcry_md_close (md);
ksba_free (p);
return gpg_error (GPG_ERR_BUG);
}
+ rc = gcry_sexp_sscan ( &s_sig, NULL, (char*)p, n);
+ ksba_free (p);
+ if (rc)
+ {
+ log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
+ return rc;
+ }
if (DBG_CRYPTO)
+ gcry_log_debugsxp ("sigval", s_sig);
+
+ if (use_pss)
{
- int j;
- log_debug ("signature value:");
- for (j=0; j < n; j++)
- log_printf (" %02X", p[j]);
- log_printf ("\n");
+ rc = extract_pss_params (s_sig, &algo, &saltlen);
+ if (rc)
+ {
+ gcry_sexp_release (s_sig);
+ return rc;
+ }
}
- rc = gcry_sexp_sscan ( &s_sig, NULL, (char*)p, n);
- ksba_free (p);
+
+ /* Hash the to-be-signed parts of the certificate. */
+ rc = gcry_md_open (&md, algo, 0);
if (rc)
{
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
+ log_error ("md_open failed: %s\n", gpg_strerror (rc));
+ return rc;
+ }
+ if (DBG_HASHING)
+ gcry_md_debug (md, "hash.cert");
+
+ rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
+ if (rc)
+ {
+ log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc));
gcry_md_close (md);
return rc;
}
+ gcry_md_final (md);
+ /* Get the public key from the certificate. */
p = ksba_cert_get_public_key (issuer_cert);
n = gcry_sexp_canon_len (p, 0, NULL, NULL);
if (!n)
@@ -308,29 +441,50 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
gcry_sexp_release (s_sig);
return rc;
}
+ if (DBG_CRYPTO)
+ gcry_log_debugsxp ("pubkey:", s_pkey);
- rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey),
- gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
- if (rc)
+ if (use_pss)
{
- gcry_md_close (md);
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_pkey);
- return rc;
+ rc = gcry_sexp_build (&s_data, NULL,
+ "(data (flags pss)"
+ "(hash %s %b)"
+ "(salt-length %u))",
+ hash_algo_to_string (algo),
+ (int)gcry_md_get_algo_dlen (algo),
+ gcry_md_read (md, algo),
+ saltlen);
+ if (rc)
+ BUG ();
}
+ else
+ {
+ /* RSA or DSA: Prepare the hash for verification. */
+ gcry_mpi_t frame;
- /* put hash into the S-Exp s_hash */
- if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
- BUG ();
- gcry_mpi_release (frame);
-
+ rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey),
+ gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
+ if (rc)
+ {
+ gcry_md_close (md);
+ gcry_sexp_release (s_sig);
+ gcry_sexp_release (s_pkey);
+ return rc;
+ }
+ if ( gcry_sexp_build (&s_data, NULL, "%m", frame) )
+ BUG ();
+ gcry_mpi_release (frame);
+ }
+ if (DBG_CRYPTO)
+ gcry_log_debugsxp ("data:", s_data);
- rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
+ /* Verify. */
+ rc = gcry_pk_verify (s_sig, s_data, s_pkey);
if (DBG_X509)
log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
gcry_md_close (md);
gcry_sexp_release (s_sig);
- gcry_sexp_release (s_hash);
+ gcry_sexp_release (s_data);
gcry_sexp_release (s_pkey);
return rc;
}
@@ -338,30 +492,41 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
int
-gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
- gcry_md_hd_t md, int mdalgo, int *r_pkalgo)
+gpgsm_check_cms_signature (ksba_cert_t cert, gcry_sexp_t s_sig,
+ gcry_md_hd_t md, int mdalgo,
+ unsigned int pkalgoflags, int *r_pkalgo)
{
int rc;
ksba_sexp_t p;
- gcry_mpi_t frame;
- gcry_sexp_t s_sig, s_hash, s_pkey;
+ gcry_sexp_t s_hash, s_pkey;
size_t n;
int pkalgo;
+ int use_pss;
+ unsigned int saltlen = 0;
if (r_pkalgo)
*r_pkalgo = 0;
- n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- return gpg_error (GPG_ERR_BUG);
- }
- rc = gcry_sexp_sscan (&s_sig, NULL, (char*)sigval, n);
- if (rc)
+ /* Check whether rsaPSS is needed. This information is indicated in
+ * the SIG-VAL and already provided to us by the caller so that we
+ * do not need to parse this out. */
+ use_pss = !!(pkalgoflags & PK_ALGO_FLAG_RSAPSS);
+ if (use_pss)
{
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- return rc;
+ int algo;
+
+ rc = extract_pss_params (s_sig, &algo, &saltlen);
+ if (rc)
+ {
+ gcry_sexp_release (s_sig);
+ return rc;
+ }
+ if (algo != mdalgo)
+ {
+ log_error ("PSS hash algo mismatch (%d/%d)\n", mdalgo, algo);
+ gcry_sexp_release (s_sig);
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
}
p = ksba_cert_get_public_key (cert);
@@ -370,41 +535,57 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
{
log_error ("libksba did not return a proper S-Exp\n");
ksba_free (p);
- gcry_sexp_release (s_sig);
return gpg_error (GPG_ERR_BUG);
}
if (DBG_CRYPTO)
- log_printhex ("public key: ", p, n);
+ log_printhex (p, n, "public key: ");
rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n);
ksba_free (p);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- gcry_sexp_release (s_sig);
return rc;
}
pkalgo = pk_algo_from_sexp (s_pkey);
if (r_pkalgo)
*r_pkalgo = pkalgo;
- rc = do_encode_md (md, mdalgo, pkalgo,
- gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
- if (rc)
+
+ if (use_pss)
{
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_pkey);
- return rc;
+ rc = gcry_sexp_build (&s_hash, NULL,
+ "(data (flags pss)"
+ "(hash %s %b)"
+ "(salt-length %u))",
+ hash_algo_to_string (mdalgo),
+ (int)gcry_md_get_algo_dlen (mdalgo),
+ gcry_md_read (md, mdalgo),
+ saltlen);
+ if (rc)
+ BUG ();
+ }
+ else
+ {
+ /* RSA or DSA: Prepare the hash for verification. */
+ gcry_mpi_t frame;
+
+ rc = do_encode_md (md, mdalgo, pkalgo,
+ gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
+ if (rc)
+ {
+ gcry_sexp_release (s_pkey);
+ return rc;
+ }
+ /* put hash into the S-Exp s_hash */
+ if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
+ BUG ();
+ gcry_mpi_release (frame);
}
- /* put hash into the S-Exp s_hash */
- if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
- BUG ();
- gcry_mpi_release (frame);
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_X509)
- log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
- gcry_sexp_release (s_sig);
+ log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
gcry_sexp_release (s_hash);
gcry_sexp_release (s_pkey);
return rc;
diff --git a/sm/certdump.c b/sm/certdump.c
index ede1210..c177cab 100644
--- a/sm/certdump.c
+++ b/sm/certdump.c
@@ -38,7 +38,7 @@
#include "keydb.h"
#include "../common/i18n.h"
-
+#include "../common/membuf.h"
struct dn_array_s {
char *key;
@@ -73,6 +73,85 @@ gpgsm_print_serial (estream_t fp, ksba_const_sexp_t sn)
}
+/* Print the first element of an S-Expression in decimal notation
+ * assuming it is a non-negative integer. */
+void
+gpgsm_print_serial_decimal (estream_t fp, ksba_const_sexp_t sn)
+{
+ const char *p = (const char *)sn;
+ unsigned long n, i;
+ char *endp;
+ gcry_mpi_t a, r, ten;
+#if GCRYPT_VERSION_NUMBER >= 0x010900 /* >= 1.9.0 */
+ unsigned int dd;
+#else
+ unsigned char numbuf[10];
+#endif
+
+ if (!p)
+ es_fputs (_("none"), fp);
+ else if (*p != '(')
+ es_fputs ("[Internal error - not an S-expression]", fp);
+ else
+ {
+ p++;
+ n = strtoul (p, &endp, 10);
+ p = endp;
+ if (*p++ != ':')
+ es_fputs ("[Internal Error - invalid S-expression]", fp);
+ else if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, p, n, NULL))
+ es_fputs ("[Internal Error - can't convert to decimal]", fp);
+ else
+ {
+ membuf_t mb = MEMBUF_ZERO;
+ char *buf;
+ int c;
+
+ ten = gcry_mpi_set_ui (NULL, 10);
+ r = gcry_mpi_new (0);
+
+ do
+ {
+ gcry_mpi_div (a, r, a, ten, 0);
+#if GCRYPT_VERSION_NUMBER >= 0x010900 /* >= 1.9.0 */
+ gcry_mpi_get_ui (&dd, r);
+ put_membuf_printf (&mb, "%u", dd);
+#else
+ *numbuf = 0; /* Need to clear because USB format prints
+ * an empty string for a value of 0. */
+ gcry_mpi_print (GCRYMPI_FMT_USG, numbuf, 10, NULL, r);
+ put_membuf_printf (&mb, "%u", (unsigned int)*numbuf);
+#endif
+ }
+ while (gcry_mpi_cmp_ui (a, 0));
+
+ /* Make sure we have at least an empty string, get it,
+ * reverse it, and print it. */
+ put_membuf (&mb, "", 1);
+ buf = get_membuf (&mb, NULL);
+ if (!buf)
+ es_fputs ("[Internal Error - out of core]", fp);
+ else
+ {
+ n = strlen (buf);
+ for (i=0; i < n/2; i++)
+ {
+ c = buf[i];
+ buf[i] = buf[n-1-i];
+ buf[n-1-i] = c;
+ }
+ es_fputs (buf, fp);
+ xfree (buf);
+ }
+
+ gcry_mpi_release (r);
+ gcry_mpi_release (ten);
+ gcry_mpi_release (a);
+ }
+ }
+}
+
+
/* Dump the serial number or any other simple S-expression. */
void
gpgsm_dump_serial (ksba_const_sexp_t sn)
@@ -167,7 +246,7 @@ gpgsm_dump_string (const char *string)
else
{
log_printf ( "[ ");
- log_printhex (NULL, string, strlen (string));
+ log_printhex (string, strlen (string), NULL);
log_printf ( " ]");
}
}
diff --git a/sm/certreqgen.c b/sm/certreqgen.c
index 3dec4fa..92d6ffe 100644
--- a/sm/certreqgen.c
+++ b/sm/certreqgen.c
@@ -198,7 +198,7 @@ parse_parameter_usage (struct para_data_s *para, enum para_name key)
use |= GCRY_PK_USAGE_CERT;
else
{
- log_error ("line %d: invalid usage list\n", r->lnr);
+ log_error ("line %d: invalid usage list\n", r?r->lnr:0);
return -1; /* error */
}
}
@@ -461,7 +461,10 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
if ( (i < 1 || i != GCRY_PK_RSA) && !cardkeyid )
{
r = get_parameter (para, pKEYTYPE, 0);
- log_error (_("line %d: invalid algorithm\n"), r->lnr);
+ if (r)
+ log_error (_("line %d: invalid algorithm\n"), r?r->lnr:0);
+ else
+ log_error ("No Key-Type specified\n");
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -476,7 +479,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
/* The BSI specs dated 2002-11-25 don't allow lengths below 1024. */
r = get_parameter (para, pKEYLENGTH, 0);
log_error (_("line %d: invalid key length %u (valid are %d to %d)\n"),
- r->lnr, nbits, 1024, 4096);
+ r?r->lnr:0, nbits, 1024, 4096);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -493,7 +496,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
if (!(s=get_parameter_value (para, pNAMEDN, 0)))
{
r = get_parameter (para, pNAMEDN, 0);
- log_error (_("line %d: no subject name given\n"), r->lnr);
+ log_error (_("line %d: no subject name given\n"), r?r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -503,10 +506,10 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
r = get_parameter (para, pNAMEDN, 0);
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME)
log_error (_("line %d: invalid subject name label '%.*s'\n"),
- r->lnr, (int)errlen, s+erroff);
+ r?r->lnr:0, (int)errlen, s+erroff);
else
log_error (_("line %d: invalid subject name '%s' at pos %d\n"),
- r->lnr, s, (int)erroff);
+ r?r->lnr:0, s, (int)erroff);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
@@ -522,7 +525,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
|| strstr(s, ".."))
{
r = get_parameter (para, pNAMEEMAIL, seq);
- log_error (_("line %d: not a valid email address\n"), r->lnr);
+ log_error (_("line %d: not a valid email address\n"), r?r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -541,7 +544,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
if (*s)
{
r = get_parameter (para, pSERIAL, 0);
- log_error (_("line %d: invalid serial number\n"), r->lnr);
+ log_error (_("line %d: invalid serial number\n"), r?r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -558,10 +561,10 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
r = get_parameter (para, pISSUERDN, 0);
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME)
log_error (_("line %d: invalid issuer name label '%.*s'\n"),
- r->lnr, (int)errlen, string+erroff);
+ r?r->lnr:0, (int)errlen, string+erroff);
else
log_error (_("line %d: invalid issuer name '%s' at pos %d\n"),
- r->lnr, string, (int)erroff);
+ r?r->lnr:0, string, (int)erroff);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -572,7 +575,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
if (string && !string2isotime (NULL, string))
{
r = get_parameter (para, pNOTBEFORE, 0);
- log_error (_("line %d: invalid date given\n"), r->lnr);
+ log_error (_("line %d: invalid date given\n"), r?r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -583,7 +586,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
if (string && !string2isotime (NULL, string))
{
r = get_parameter (para, pNOTAFTER, 0);
- log_error (_("line %d: invalid date given\n"), r->lnr);
+ log_error (_("line %d: invalid date given\n"), r?r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -597,7 +600,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
{
r = get_parameter (para, pKEYTYPE, 0);
log_error (_("line %d: error getting signing key by keygrip '%s'"
- ": %s\n"), r->lnr, s, gpg_strerror (rc));
+ ": %s\n"), r?r->lnr:0, s, gpg_strerror (rc));
xfree (cardkeyid);
return rc;
}
@@ -615,7 +618,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
|| mdalgo == GCRY_MD_SHA512)))
{
r = get_parameter (para, pHASHALGO, 0);
- log_error (_("line %d: invalid hash algorithm given\n"), r->lnr);
+ log_error (_("line %d: invalid hash algorithm given\n"), r?r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -630,7 +633,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
if (*s || (i&1))
{
r = get_parameter (para, pAUTHKEYID, 0);
- log_error (_("line %d: invalid authority-key-id\n"), r->lnr);
+ log_error (_("line %d: invalid authority-key-id\n"), r?r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -645,7 +648,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
if (*s || (i&1))
{
r = get_parameter (para, pSUBJKEYID, 0);
- log_error (_("line %d: invalid subject-key-id\n"), r->lnr);
+ log_error (_("line %d: invalid subject-key-id\n"), r?r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -683,7 +686,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
if (!okay)
{
r = get_parameter (para, pEXTENSION, seq);
- log_error (_("line %d: invalid extension syntax\n"), r->lnr);
+ log_error (_("line %d: invalid extension syntax\n"), r? r->lnr:0);
xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -697,7 +700,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
{
r = get_parameter (para, pKEYTYPE, 0);
log_error (_("line %d: error reading key '%s' from card: %s\n"),
- r->lnr, cardkeyid, gpg_strerror (rc));
+ r?r->lnr:0, cardkeyid, gpg_strerror (rc));
xfree (sigkey);
xfree (cardkeyid);
return rc;
@@ -727,7 +730,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
{
r = get_parameter (para, pKEYTYPE, 0);
log_error (_("line %d: key generation failed: %s <%s>\n"),
- r->lnr, gpg_strerror (rc), gpg_strsource (rc));
+ r?r->lnr:0, gpg_strerror (rc), gpg_strsource (rc));
xfree (sigkey);
xfree (cardkeyid);
return rc;
diff --git a/sm/decrypt.c b/sm/decrypt.c
index db0768e..90eba88 100644
--- a/sm/decrypt.c
+++ b/sm/decrypt.c
@@ -72,7 +72,7 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
}
if (DBG_CRYPTO)
- log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
+ log_printhex (seskey, seskeylen, "pkcs1 encoded session key:");
n=0;
if (seskeylen == 32 || seskeylen == 24 || seskeylen == 16)
@@ -115,7 +115,7 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
}
if (DBG_CRYPTO)
- log_printhex ("session key:", seskey+n, seskeylen-n);
+ log_printhex (seskey+n, seskeylen-n, "session key:");
rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
if (rc)
@@ -483,7 +483,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
/* Check compliance. */
if (!gnupg_pk_is_allowed (opt.compliance,
PK_USE_DECRYPTION,
- pk_algo, NULL, nbits, NULL))
+ pk_algo, 0, NULL, nbits, NULL))
{
char kidstr[10+1];
@@ -501,7 +501,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
/* Check that all certs are compliant with CO_DE_VS. */
is_de_vs =
(is_de_vs
- && gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL,
+ && gnupg_pk_is_compliant (CO_DE_VS, pk_algo, 0, NULL,
nbits, NULL));
}
diff --git a/sm/encrypt.c b/sm/encrypt.c
index 6213a66..f03097c 100644
--- a/sm/encrypt.c
+++ b/sm/encrypt.c
@@ -480,7 +480,8 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
/* Check compliance. */
pk_algo = gpgsm_get_key_algo_info (cl->cert, &nbits);
- if (!gnupg_pk_is_compliant (opt.compliance, pk_algo, NULL, nbits, NULL))
+ if (!gnupg_pk_is_compliant (opt.compliance, pk_algo, 0,
+ NULL, nbits, NULL))
{
char kidstr[10+1];
@@ -495,7 +496,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
/* Fixme: When adding ECC we need to provide the curvename and
* the key to gnupg_pk_is_compliant. */
if (compliant
- && !gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL, nbits, NULL))
+ && !gnupg_pk_is_compliant (CO_DE_VS, pk_algo, 0, NULL, nbits, NULL))
compliant = 0;
rc = encrypt_dek (dek, cl->cert, &encval);
diff --git a/sm/fingerprint.c b/sm/fingerprint.c
index fbcec58..2e01cf1 100644
--- a/sm/fingerprint.c
+++ b/sm/fingerprint.c
@@ -196,7 +196,7 @@ gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array)
return NULL;
}
if (DBG_X509)
- log_printhex ("keygrip=", array, 20);
+ log_printhex (array, 20, "keygrip=");
return array;
}
@@ -277,6 +277,41 @@ gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits)
}
+/* This is a wrapper around pubkey_algo_string which takes a KSBA
+ * certificate instead of a Gcrypt public key. Note that this
+ * function may return NULL on error. */
+char *
+gpgsm_pubkey_algo_string (ksba_cert_t cert, int *r_algoid)
+{
+ gpg_error_t err;
+ gcry_sexp_t s_pkey;
+ ksba_sexp_t p;
+ size_t n;
+ enum gcry_pk_algos algoid;
+ char *algostr;
+
+ p = ksba_cert_get_public_key (cert);
+ if (!p)
+ return NULL;
+ n = gcry_sexp_canon_len (p, 0, NULL, NULL);
+ if (!n)
+ {
+ xfree (p);
+ return NULL;
+ }
+ err = gcry_sexp_sscan (&s_pkey, NULL, (char *)p, n);
+ xfree (p);
+ if (err)
+ return NULL;
+
+ algostr = pubkey_algo_string (s_pkey, r_algoid? &algoid : NULL);
+ if (algostr && r_algoid)
+ *r_algoid = algoid;
+
+ gcry_sexp_release (s_pkey);
+ return algostr;
+}
+
/* For certain purposes we need a certificate id which has an upper
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 387e4d2..bb27672 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -144,6 +144,7 @@ enum cmd_and_opt_values {
oDisableTrustedCertCRLCheck,
oEnableTrustedCertCRLCheck,
oForceCRLRefresh,
+ oEnableIssuerBasedCRLCheck,
oDisableOCSP,
oEnableOCSP,
@@ -402,6 +403,8 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oNoCommonCertsImport, "no-common-certs-import", "@"),
ARGPARSE_s_s (oIgnoreCertExtension, "ignore-cert-extension", "@"),
ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
+ ARGPARSE_s_n (oEnableIssuerBasedCRLCheck, "enable-issuer-based-crl-check",
+ "@"),
/* Command aliases. */
ARGPARSE_c (aListKeys, "list-key", "@"),
@@ -1202,6 +1205,9 @@ main ( int argc, char **argv)
case oForceCRLRefresh:
opt.force_crl_refresh = 1;
break;
+ case oEnableIssuerBasedCRLCheck:
+ opt.enable_issuer_based_crl_check = 1;
+ break;
case oDisableOCSP:
ctrl.use_ocsp = opt.enable_ocsp = 0;
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index a9fb4c8..d128344 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -124,6 +124,7 @@ struct
int no_crl_check; /* Don't do a CRL check */
int no_trusted_cert_crl_check; /* Don't run a CRL check for trusted certs. */
int force_crl_refresh; /* Force refreshing the CRL. */
+ int enable_issuer_based_crl_check; /* Backward compatibility hack. */
int enable_ocsp; /* Default to use OCSP checks. */
char *policy_file; /* full pathname of policy file */
@@ -263,11 +264,13 @@ unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert,
unsigned char *gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array);
char *gpgsm_get_keygrip_hexstring (ksba_cert_t cert);
int gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits);
+char *gpgsm_pubkey_algo_string (ksba_cert_t cert, int *r_algoid);
char *gpgsm_get_certid (ksba_cert_t cert);
/*-- certdump.c --*/
void gpgsm_print_serial (estream_t fp, ksba_const_sexp_t p);
+void gpgsm_print_serial_decimal (estream_t fp, ksba_const_sexp_t sn);
void gpgsm_print_time (estream_t fp, ksba_isotime_t t);
void gpgsm_print_name2 (FILE *fp, const char *string, int translate);
void gpgsm_print_name (FILE *fp, const char *string);
@@ -293,8 +296,10 @@ char *gpgsm_format_keydesc (ksba_cert_t cert);
/*-- certcheck.c --*/
int gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert);
-int gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
- gcry_md_hd_t md, int hash_algo, int *r_pkalgo);
+int gpgsm_check_cms_signature (ksba_cert_t cert, gcry_sexp_t sigval,
+ gcry_md_hd_t md,
+ int hash_algo, unsigned int pkalgoflags,
+ int *r_pkalgo);
/* fixme: move create functions to another file */
int gpgsm_create_cms_signature (ctrl_t ctrl,
ksba_cert_t cert, gcry_md_hd_t md, int mdalgo,
@@ -423,7 +428,8 @@ gpg_error_t gpgsm_agent_export_key (ctrl_t ctrl, const char *keygrip,
int gpgsm_dirmngr_isvalid (ctrl_t ctrl,
ksba_cert_t cert, ksba_cert_t issuer_cert,
int use_ocsp);
-int gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
+int gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, const char *uri,
+ int cache_only,
void (*cb)(void*, ksba_cert_t), void *cb_value);
int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
int argc, char **argv);
@@ -435,6 +441,9 @@ gpg_error_t transform_sigval (const unsigned char *sigval, size_t sigvallen,
int mdalgo,
unsigned char **r_newsigval,
size_t *r_newsigvallen);
+gcry_sexp_t gpgsm_ksba_cms_get_sig_val (ksba_cms_t cms, int idx);
+int gpgsm_get_hash_algo_from_sigval (gcry_sexp_t sigval,
+ unsigned int *r_pkalgo_flags);
diff --git a/sm/import.c b/sm/import.c
index 8796cd2..ca69382 100644
--- a/sm/import.c
+++ b/sm/import.c
@@ -836,7 +836,7 @@ parse_p12 (ctrl_t ctrl, ksba_reader_t reader, struct stats_s *stats)
log_error ("can't calculate keygrip\n");
goto leave;
}
- log_printhex ("keygrip=", grip, 20);
+ log_printhex (grip, 20, "keygrip=");
/* Convert to canonical encoding using a function which pads it to a
multiple of 64 bits. We need this padding for AESWRAP. */
diff --git a/sm/keylist.c b/sm/keylist.c
index 6efc6bd..8c7fafc 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -361,7 +361,10 @@ print_compliance_flags (ksba_cert_t cert, int algo, unsigned int nbits,
{
int hashalgo;
- if (gnupg_pk_is_compliant (CO_DE_VS, algo, NULL, nbits, NULL))
+ /* Note that we do not need to test for PK_ALGO_FLAG_RSAPSS because
+ * that is not a property of the key but one of the created
+ * signature. */
+ if (gnupg_pk_is_compliant (CO_DE_VS, algo, 0, NULL, nbits, NULL))
{
hashalgo = gcry_md_map_name (ksba_cert_get_digest_algo (cert));
if (gnupg_digest_is_compliant (CO_DE_VS, hashalgo))
@@ -738,8 +741,11 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
sexp = ksba_cert_get_serial (cert);
es_fputs (" S/N: ", fp);
gpgsm_print_serial (fp, sexp);
- ksba_free (sexp);
es_putc ('\n', fp);
+ es_fputs (" (dec): ", fp);
+ gpgsm_print_serial_decimal (fp, sexp);
+ es_putc ('\n', fp);
+ ksba_free (sexp);
dn = ksba_cert_get_issuer (cert, 0);
es_fputs (" Issuer: ", fp);
@@ -1118,8 +1124,11 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
sexp = ksba_cert_get_serial (cert);
es_fputs (" S/N: ", fp);
gpgsm_print_serial (fp, sexp);
- ksba_free (sexp);
es_putc ('\n', fp);
+ es_fputs (" (dec): ", fp);
+ gpgsm_print_serial_decimal (fp, sexp);
+ es_putc ('\n', fp);
+ ksba_free (sexp);
dn = ksba_cert_get_issuer (cert, 0);
es_fputs (" Issuer: ", fp);
@@ -1607,7 +1616,7 @@ list_external_keys (ctrl_t ctrl, strlist_t names, estream_t fp, int raw_mode)
parm.with_chain = ctrl->with_chain;
parm.raw_mode = raw_mode;
- rc = gpgsm_dirmngr_lookup (ctrl, names, 0, list_external_cb, &parm);
+ rc = gpgsm_dirmngr_lookup (ctrl, names, NULL, 0, list_external_cb, &parm);
if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1
|| gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0; /* "Not found" is not an error here. */
diff --git a/sm/misc.c b/sm/misc.c
index 6d04776..66d928c 100644
--- a/sm/misc.c
+++ b/sm/misc.c
@@ -216,3 +216,93 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo,
return err;
}
+
+
+/* Wrapper around ksba_cms_get_sig_val to return a gcrypt object
+ * instaed of ksba's canonical s-expression. On errror NULL is return
+ * and in some cases an error message is printed. */
+gcry_sexp_t
+gpgsm_ksba_cms_get_sig_val (ksba_cms_t cms, int idx)
+{
+ gpg_error_t err;
+ ksba_sexp_t sigval;
+ gcry_sexp_t s_sigval;
+ size_t n;
+
+ sigval = ksba_cms_get_sig_val (cms, idx);
+ if (!sigval)
+ return NULL;
+ n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
+ if (!n)
+ {
+ log_error ("%s: libksba did not return a proper S-Exp\n", __func__);
+ ksba_free (sigval);
+ return NULL;
+ }
+ err = gcry_sexp_sscan (&s_sigval, NULL, (char*)sigval, n);
+ ksba_free (sigval);
+ if (err)
+ {
+ log_error ("%s: gcry_sexp_scan failed: %s\n",
+ __func__, gpg_strerror (err));
+ s_sigval = NULL;
+ }
+
+ return s_sigval;
+}
+
+
+/* Return the hash algorithm from the S-expression SIGVAL. Returns 0
+ * if the hash algorithm is not encoded in SIGVAL or it is not
+ * supported by libgcrypt. It further stores flag values for the
+ * public key algorithm at R_PKALGO_FLAGS; the only flag we currently
+ * support is PK_ALGO_FLAG_RSAPSS. */
+int
+gpgsm_get_hash_algo_from_sigval (gcry_sexp_t sigval_arg,
+ unsigned int *r_pkalgo_flags)
+{
+ gcry_sexp_t sigval, l1;
+ size_t n;
+ const char *s;
+ char *string;
+ int hashalgo;
+ int i;
+
+ *r_pkalgo_flags = 0;
+
+ sigval = gcry_sexp_find_token (sigval_arg, "sig-val", 0);
+ if (!sigval)
+ return 0; /* Not a sig-val. */
+
+ /* First check whether this is a rsaPSS signature and return that as
+ * additional info. */
+ l1 = gcry_sexp_find_token (sigval, "flags", 0);
+ if (l1)
+ {
+ /* Note that the flag parser assumes that the list of flags
+ * contains only strings and in particular not a sub-list. This
+ * is always the case for the current libksba. */
+ for (i=1; (s = gcry_sexp_nth_data (l1, i, &n)); i++)
+ if (n == 3 && !memcmp (s, "pss", 3))
+ {
+ *r_pkalgo_flags |= PK_ALGO_FLAG_RSAPSS;
+ break;
+ }
+ gcry_sexp_release (l1);
+ }
+
+ l1 = gcry_sexp_find_token (sigval, "hash", 0);
+ if (!l1)
+ {
+ gcry_sexp_release (sigval);
+ return 0; /* hash algorithm not given in sigval. */
+ }
+ string = gcry_sexp_nth_string (l1, 1);
+ gcry_sexp_release (sigval);
+ if (!string)
+ return 0; /* hash algorithm has no value. */
+ hashalgo = gcry_md_map_name (string);
+ gcry_free (string);
+
+ return hashalgo;
+}
diff --git a/sm/sign.c b/sm/sign.c
index fd6ebe0..dd7612f 100644
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -486,7 +486,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
unsigned int nbits;
int pk_algo = gpgsm_get_key_algo_info (cl->cert, &nbits);
- if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING, pk_algo,
+ if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING, pk_algo, 0,
NULL, nbits, NULL))
{
char kidstr[10+1];
diff --git a/sm/verify.c b/sm/verify.c
index 10b3f43..0fa365f 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -1,6 +1,8 @@
/* verify.c - Verify a messages signature
* Copyright (C) 2001, 2002, 2003, 2007,
* 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2001-2019 Werner Koch
+ * Copyright (C) 2015-2020 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -16,6 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <config.h>
@@ -286,7 +289,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
for (signer=0; ; signer++)
{
char *issuer = NULL;
- ksba_sexp_t sigval = NULL;
+ gcry_sexp_t sigval = NULL;
ksba_isotime_t sigtime, keyexptime;
ksba_sexp_t serial;
char *msgdigest = NULL;
@@ -294,7 +297,11 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
char *ctattr;
int sigval_hash_algo;
int info_pkalgo;
- unsigned int verifyflags;
+ unsigned int nbits;
+ int pkalgo;
+ char *pkalgostr = NULL;
+ char *pkfpr = NULL;
+ unsigned int pkalgoflags, verifyflags;
rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
@@ -400,20 +407,19 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
rc = 0;
- sigval = ksba_cms_get_sig_val (cms, signer);
+ sigval = gpgsm_ksba_cms_get_sig_val (cms, signer);
if (!sigval)
{
log_error ("no signature value available\n");
audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
goto next_signer;
}
- sigval_hash_algo = hash_algo_from_sigval (sigval);
+
+ sigval_hash_algo = gpgsm_get_hash_algo_from_sigval (sigval, &pkalgoflags);
if (DBG_X509)
{
- log_debug ("signer %d - signature available (sigval hash=%d)",
- signer, sigval_hash_algo);
-/* log_printhex ("sigval ", sigval, */
-/* gcry_sexp_canon_len (sigval, 0, NULL, NULL)); */
+ log_debug ("signer %d - signature available (sigval hash=%d pkaf=%u)",
+ signer, sigval_hash_algo, pkalgoflags);
}
if (!sigval_hash_algo)
sigval_hash_algo = algo; /* Fallback used e.g. with old libksba. */
@@ -450,49 +456,68 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
goto next_signer;
}
- /* Check compliance. */
- {
- unsigned int nbits;
- int pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
-
- if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
- pk_algo, NULL, nbits, NULL))
- {
- char kidstr[10+1];
-
- snprintf (kidstr, sizeof kidstr, "0x%08lX",
- gpgsm_get_short_fingerprint (cert, NULL));
- log_error (_("key %s may not be used for signing in %s mode\n"),
- kidstr,
- gnupg_compliance_option_string (opt.compliance));
- goto next_signer;
- }
-
- if (! gnupg_digest_is_allowed (opt.compliance, 0, sigval_hash_algo))
- {
- log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
- gcry_md_algo_name (sigval_hash_algo),
- gnupg_compliance_option_string (opt.compliance));
- goto next_signer;
- }
-
- /* Check compliance with CO_DE_VS. */
- if (gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL, nbits, NULL)
- && gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo))
- gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE,
- gnupg_status_compliance_flag (CO_DE_VS));
- }
+ pkfpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
+ pkalgostr = gpgsm_pubkey_algo_string (cert, NULL);
+ pkalgo = gpgsm_get_key_algo_info (cert, &nbits);
log_info (_("Signature made "));
if (*sigtime)
- dump_isotime (sigtime);
+ {
+ /* We take the freedom as noted in RFC3339 to use a space
+ * instead of the "T" delimiter between date and time. We
+ * also append a separate UTC instead of a "Z" or "+00:00"
+ * suffix because that makes it clear to everyone what kind
+ * of time this is. */
+ dump_isotime (sigtime);
+ log_printf (" UTC");
+ }
else
log_printf (_("[date not given]"));
- log_printf (_(" using certificate ID 0x%08lX\n"),
- gpgsm_get_short_fingerprint (cert, NULL));
+ log_info (_(" using %s key %s\n"), pkalgostr, pkfpr);
+ if (opt.verbose)
+ {
+ log_info (_("algorithm:"));
+ log_printf (" %s + %s",
+ pubkey_algo_to_string (pkalgo),
+ gcry_md_algo_name (sigval_hash_algo));
+ if (algo != sigval_hash_algo)
+ log_printf (" (%s)", gcry_md_algo_name (algo));
+ log_printf ("\n");
+ }
audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
+ /* Check compliance. */
+ if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
+ pkalgo, pkalgoflags, NULL, nbits, NULL))
+ {
+ char kidstr[10+1];
+
+ snprintf (kidstr, sizeof kidstr, "0x%08lX",
+ gpgsm_get_short_fingerprint (cert, NULL));
+ log_error (_("key %s may not be used for signing in %s mode\n"),
+ kidstr,
+ gnupg_compliance_option_string (opt.compliance));
+ goto next_signer;
+ }
+
+ if (!gnupg_digest_is_allowed (opt.compliance, 0, sigval_hash_algo))
+ {
+ log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+ gcry_md_algo_name (sigval_hash_algo),
+ gnupg_compliance_option_string (opt.compliance));
+ goto next_signer;
+ }
+
+ /* Check compliance with CO_DE_VS. */
+ if (gnupg_pk_is_compliant (CO_DE_VS, pkalgo, pkalgoflags,
+ NULL, nbits, NULL)
+ && gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo))
+ gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE,
+ gnupg_status_compliance_flag (CO_DE_VS));
+
+
+ /* Now we can check the signature. */
if (msgdigest)
{ /* Signed attributes are available. */
gcry_md_hd_t md;
@@ -512,10 +537,10 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
if (DBG_X509)
{
if (msgdigest)
- log_printhex ("message: ", msgdigest, msgdigestlen);
+ log_printhex (msgdigest, msgdigestlen, "message: ");
if (s)
- log_printhex ("computed: ",
- s, gcry_md_get_algo_dlen (algo));
+ log_printhex (s, gcry_md_get_algo_dlen (algo),
+ "computed: ");
}
fpr = gpgsm_fpr_and_name_for_status (cert);
gpgsm_status (ctrl, STATUS_BADSIG, fpr);
@@ -545,14 +570,14 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
goto next_signer;
}
- rc = gpgsm_check_cms_signature (cert, sigval, md,
- sigval_hash_algo, &info_pkalgo);
+ rc = gpgsm_check_cms_signature (cert, sigval, md, sigval_hash_algo,
+ pkalgoflags, &info_pkalgo);
gcry_md_close (md);
}
else
{
rc = gpgsm_check_cms_signature (cert, sigval, data_md,
- algo, &info_pkalgo);
+ algo, pkalgoflags, &info_pkalgo);
}
if (rc)
@@ -669,8 +694,10 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
rc = 0;
xfree (issuer);
xfree (serial);
- xfree (sigval);
+ gcry_sexp_release (sigval);
xfree (msgdigest);
+ xfree (pkalgostr);
+ xfree (pkfpr);
ksba_cert_release (cert);
cert = NULL;
}
diff --git a/tools/send-mail.c b/tools/send-mail.c
index 9f07c7a..6492c43 100644
--- a/tools/send-mail.c
+++ b/tools/send-mail.c
@@ -33,7 +33,7 @@ static gpg_error_t
run_sendmail (estream_t data)
{
gpg_error_t err;
- const char pgmname[] = "/usr/lib/sendmail";
+ const char pgmname[] = NAME_OF_SENDMAIL;
const char *argv[3];
argv[0] = "-oi";