Compare commits

...

274 Commits

Author SHA1 Message Date
Werner Koch 351fc6e6fa
gpg: Algo "kyber" is now a shortcut for ky768_bp256.
* g10/keygen.c (parse_key_parameter_part): Change Kyber defaults.
--

Also kyber1024 is now a shortcut for ky1024_bp384.  This change is to
align it with the original wussler draft.
2024-05-06 10:47:01 +02:00
Werner Koch 473f37a53e
scd:piv: Support listing of retired keys with KEYINFO.
* scd/app-piv.c (data_objects): Mark returned key as having a keypair.
(do_with_keygrip): Check against encrusage and not used one tag.

* tools/gpg-card.c (piv_keyref_is_retired): New.
(list_all_kinfo): Pretty print retired keys.
--

This allows to list all existing retired keys without using separate
readkey commands.
2024-05-06 09:48:20 +02:00
Werner Koch 467239dccb
speedo: Update the instructions to use the gnupg26 tag.
--
2024-05-02 21:13:32 +02:00
Werner Koch f415d96fac
gpg: Add a notation to Kyber encryption subkeys
* g10/keygen.c (struct opaque_data_usage_and_pk): New.
(do_add_notation): New.
(keygen_add_key_flags_from_oduap): New.
(write_keybinding): Prepare for de-vs cplimance notation.  Add a
notation to Kyber subkeys.
--

This code is based on the 2.2
commit b284412786
However the de-vs notation is currently ineffective as long as
Libgcrypt won't claim compliance.

The new notation fips203.ipd.2023-08-24 has been added to allow
detection of subkeys which have been crated with a pre-final FIPS203
spec for Kyber.
2024-05-02 21:11:55 +02:00
Werner Koch 516b530126
speedo: Change install directory for Windows
--

Given that we will build only 64 bit versions, we need to switch where
stuff is installed on Windows.
2024-04-26 15:17:49 +02:00
Werner Koch c8a3b711f0
speedo: Do not use the gpg-error-config in the build system
--

With that installed we don't get proper suport for SYSROOT.
2024-04-26 15:17:49 +02:00
Werner Koch c1d62418d5
speedo: Prepare for building 64 bit Windows versions.
--
2024-04-26 15:17:48 +02:00
Werner Koch 351f5e814b
speedo: Set gnupg_ver macro to gnupg26_ver.
--

Also fixed a syntax erro rin AUTHENTICODE_sign
2024-04-26 15:17:48 +02:00
NIIBE Yutaka 9128d81bb7
agent:kem:ecc: Support a key on smartcard.
* agent/agent.h (agent_card_ecc_kem): New.
* agent/divert-scd.c (agent_card_ecc_kem): New.
* agent/pkdecrypt.c (ecc_extract_pk_from_key): New.
(ecc_extract_sk_from_key): New.
(ecc_raw_kem, get_cardkey, ecc_get_curve): New.
(ecc_pgp_kem_decrypt): Support a key on smartcard for ECC.
(composite_pgp_kem_decrypt): Handle a case of a key on smartcard.
* common/sexputil.c (get_ecc_curve_from_key): New.
* common/util.h (get_ecc_curve_from_key): New.

--

GnuPG-bug-id: 7097
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-26 14:18:03 +09:00
Werner Koch 83e2dede0a
speedo: Use gpg-authcode-sign.sh and change archive label to v2.5.
--
2024-04-25 11:37:53 +02:00
Werner Koch d3b41e7611
Install the new gpg-authcode-sign.sh script.
* tools/gpg-authcode-sign.sh: New.
* tools/Makefile.am (bin_SCRIPTS): Add that tool.
--

This script makes use of gpg anyway and thus it is best to have it
also installed with the gpg version used to cross-build our software.
The script was orginally developed for gpg4win.
2024-04-25 11:00:18 +02:00
NIIBE Yutaka 02b056ef77
agent:kem: Fix memory leaks.
* agent/pkdecrypt.c (composite_pgp_kem_decrypt): Release shadow_info
memory.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-25 13:51:47 +09:00
NIIBE Yutaka 2593dcbceb
agent: Allow NULL for R_PADDING, when calling scd and tpm2d.
* agent/call-scd.c (padding_info_cb): Allow NULL.
(agent_card_pkdecrypt): Likewise.
* agent/divert-scd.c (divert_pkdecrypt): Likewise.
* agent/divert-tpm2.c (divert_tpm2_pkdecrypt): Likewise.

--

It's for RSA PKCD#1 encoding if the decrypt operation removes padding
or not.  When caller knows it's not RSA, this information is no use
and it is better to allow NULL with the variable R_PADDING.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-25 13:13:04 +09:00
Werner Koch 2958e5e4cf
gpg: New option --require-pqc-encryption
* g10/gpg.c (oRequirePQCEncryption): New.
(opts): Add option.
(main): Set option.
* g10/mainproc.c (print_pkenc_list): Print a warning.
* g10/options.h (flags): Add flag require_pqc_encryption.
* g10/getkey.c (finish_lookup): Skip non-pqc keys if the option is
set.
--

GnuPG-bug-id: 6815
2024-04-24 09:57:07 +02:00
NIIBE Yutaka a45243548e
agent:kem: Factor out ECC KEM operation from composite KEM.
* agent/pkdecrypt.c (ecc_pgp_kem_decrypt): New.
(composite_pgp_kem_decrypt): Use ecc_pgp_kem_decrypt.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-24 15:08:41 +09:00
NIIBE Yutaka d1f8caafb4
agent: Simplify diverting operation to the smartcard.
* agent/pkdecrypt.c (agent_pkdecrypt): Remove no_shadow_info variable.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-24 14:01:41 +09:00
Werner Koch ab703eacf7
gpg: Split keygrip in a standard key listing.
* g10/keylist.c (print_keygrip): New.
(list_keyblock_print): Use new function to print the keygrip.
2024-04-23 20:12:57 +02:00
Werner Koch dd650b2c7b
gpg: Support Kyber with Brainpool512r1.
* common/openpgp-oid.c (oidtable): Add GCRY_KEM_RAW_BP512.
* agent/pkdecrypt.c (ecc_table): Support bp512
* g10/pkglue.c (do_encrypt_kem): Ditto.

* tests/openpgp/samplekeys: Add sample keys for kyber_bp256, bp384,
and bp512.
* tests/openpgp/privkeys: Add corresponding private keys.
* tests/openpgp/samplemsgs:  Add sample messages for those keys.
--

GnuPG-bug-id: 6815
2024-04-23 17:41:28 +02:00
Werner Koch 32ec480024
gpg: Support encryption with kyber_bp256 and kyber_bp384
* common/openpgp-oid.c (oidtable): Support KEM for bp256 and bp384.
* g10/pkglue.c (do_encrypt_kem): Ditto.
--

GnuPG-bug-id: 6815

Note, this needs the very latest Libgcrypt to work properly
2024-04-23 16:25:05 +02:00
Werner Koch 54741685ce
Remove the deprecated gcry_set_log_handler.
* common/miscellaneous.c (my_gcry_logger): Remove.
(setup_libgcrypt_logging): Do not call the deprecated
gcry_set_log_handler.
* kbx/kbxutil.c (my_gcry_logger): Remove.
* tools/no-libgcrypt.c (gcry_set_log_handler): Remove stub.
2024-04-23 16:21:49 +02:00
Werner Koch f325d3277e
tests: Add two Kyber sample keys and messages.
--

GnuPG-bug-id: 6815
2024-04-23 14:04:41 +02:00
Werner Koch e591fd25ad
gpg: Support encryption with kyber_cv448.
* g10/pkglue.c (do_encrypt_kem): Support cv25519 w/o 0x40
prefix. Support X448.
(ECC_POINT_LEN_MAX): New.
(ECC_HASH_LEN_MAX): New.
* common/openpgp-oid.c (oidtable): Support X448 KEM.
--

This needs more work.  For example we should use a parameter table
like what we do in agent/pkdecrypt.c.

GnuPG-bug-id: 6815
2024-04-23 11:31:49 +02:00
Werner Koch f305e703d5
Require Libgcrypt 1.11.0
* configure.ac (NEED_LIBGCRYPT_VERSION): Set to 1.11.0
* agent/pkdecrypt.c (struct ecc_params): Move constants to the top.
--

It does not make anymore sense to allow building with older Libgcrypt
versions.  After all PQ key support is a major feature and for this we
need Libgcrypt.
2024-04-23 11:09:40 +02:00
NIIBE Yutaka af98a3e5fa
agent:kem: More fix for PQC KEM with X448.
* agent/pkdecrypt.c (struct ecc_params): Remove NAME_LEN field.
(ecc_table): Update.
(get_ecc_params): Use strcmp.
(composite_pgp_kem_decrypt): Fix the call of gnupg_kem_combiner.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-23 16:09:02 +09:00
NIIBE Yutaka 65833eefb2
agent:kem: Support other ML-KEM variants.
* agent/pkdecrypt.c (composite_pgp_kem_decrypt): Care about
ML-KEM 512 and 1024.

--

Co-authored-by: Werner Koch <wk@gnupg.org>
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-23 14:40:27 +09:00
NIIBE Yutaka d5c6b52e59
agent:kem: Support other ECC curves.
* agent/pkdecrypt.c (ecc_table): New.
(get_ecc_params): New.
(composite_pgp_kem_decrypt): Support other curves.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-23 14:23:27 +09:00
Daniel Cerqueira aa15272ba1
po: Update Portuguese Translation.
Signed-off-by: Daniel Cerqueira <dan.git@lispclub.com>
2024-04-23 09:23:34 +09:00
Werner Koch f119444e64
tests: Avoid new C23 keyword true.
* tests/asschk.c (eval_boolean): s/true/tru/
--

GnuPG-bug-is: 7093
2024-04-22 08:04:27 +02:00
Werner Koch ba3c873934
gpg: Prepare Kyber encryption code for more variants.
* common/openpgp-oid.c (oidtable): Add field kem_algo.
(openpgp_oid_to_kem_algo): New.
* g10/pkglue.c (do_encrypt_kem): Add support for Kyber1024.
--
GnuPG-bug-id: 6815
2024-04-18 14:37:40 +02:00
Werner Koch 7d6ad28667
gpg: Mark disabled keys and add show-ownertrust list option.
* g10/options.h (LIST_SHOW_OWNERTRUST): New.
* g10/keylist.c (print_key_line): Show wonertrust and always show
whether a key is disabled.
* g10/gpg.c (parse_list_options): Add "show-ownertrust".

* g10/gpgv.c (get_ownertrust_string): Add stub.
* g10/test-stubs.c (get_ownertrust_string): Add stub.
--

Note that in a --with-colons listing the ownertrust has always been
emitted and the disabled state is marked in that listing with a
special 'D' usage.
2024-04-17 12:16:20 +02:00
Werner Koch 21f7ad563d
gpg: New command --quick-set-ownertrust.
* g10/gpg.c (aQuickSetOwnertrust): New.
(opts): Add new command.
(main): Implement it.
* g10/keyedit.c (keyedit_quick_set_ownertrust): New.
2024-04-17 11:42:20 +02:00
Werner Koch 2a71c3cf97
gpg: Make --with-subkey-fingerprint the default.
* g10/gpg.c (oWithoutSubkeyFingerprint): New.
(opts): Add "without-subkey-fingerprint".
(main): Make --with-subkey-fingerprint the default.  Implementation
the without option.
--

Given that the default for the keyid format is none, the subkey
fingerprints are important to do anything with a subkey.  Thus we make
the old option the default and provide a new option to revert it.
2024-04-16 18:31:29 +02:00
Werner Koch 4e32ff209d
gpg: Fix minor Kyber display things.
* common/compliance.c (gnupg_pk_is_compliant): Make Kyber known.
* g10/misc.c (openpgp_pk_algo_name): Add "Kyber".
2024-04-15 13:25:07 +02:00
Werner Koch c736052e9c
gpg: Implement Kyber encryption.
* g10/build-packet.c (do_pubkey_enc): Support Kyber.
* g10/pkglue.c (do_encrypt_kem): Implement.
--

Note that the code does only work for ky768_cv25519 for now.

GnuPG-bug-id: 6815
2024-04-15 12:18:09 +02:00
Werner Koch 4c20d2d273
gpg: Add arg session_algo to pk_decrypt.
* common/kem.c: Move constants to the top.  Add some documentation.
* g10/pkglue.c (pk_encrypt): Add arguments session_key and factor code
out to ...
(do_encrypt_rsa_elg): here,
(do_encrypt_ecdh): and here,
(do_encrypt_kem): and here.
* g10/encrypt.c (write_pubkey_enc): Call with session key algorithm.
--

This makes it easier to review the code.
2024-04-15 09:23:54 +02:00
NIIBE Yutaka 35ef87d8d9
scd:openpgp: Robust Data Object handling for constructed case.
* scd/app-openpgp.c (get_cached_data): When it comes with
its tag and length for the constructed Data Object, remove
them.

--

GnuPG-bug-id: 7058
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-15 10:23:25 +09:00
Werner Koch b48476bbef
gpg: Prepare to use the fingerprint as fixed-info for Kyber.
* g10/pubkey-enc.c (get_it): Use algo and fingerprint for the
fixed-info.  Keep a testing mode.
* g10/options.h (COMPAT_T7014_OLD): New.
* g10/gpg.c (compatibility_flags): Add "t71014-old" flag.
--

GnuPG-bug-id: 6815
2024-04-12 11:33:07 +02:00
Werner Koch 6f94fe01a9
gpg: Simplify the pk_encrypt function interface.
* g10/pkglue.c (pk_encrypt): Remove superfluous arguments and reanem
variable rc to err.
* g10/encrypt.c (write_pubkey_enc): Adjust for this change.
--

We used to pass PK as well as information which could be taken
directly from PK.  Using ERR instead of RC is just for more uniform
naming of variables.
2024-04-12 10:43:12 +02:00
Werner Koch 813f8d1b8e
gpg: Changed internal data format for Kyber.
* g10/packet.h (PKT_pubkey_enc): Add field seskey_algo.
(struct pubkey_enc_list): Ditto.
* g10/misc.c (pubkey_get_nenc): Change value for Kyber from 4 to 3.
* g10/parse-packet.c (parse_pubkeyenc): Store the Kyber algo in the
new field and adjust data.  Do not store the length byte in data[2].
* g10/build-packet.c (do_pubkey_enc): Take the session algo for Kyber
from the new field.
* g10/encrypt.c (write_pubkey_enc): Ses the seskey_algo.
* g10/mainproc.c (proc_pubkey_enc): Copy it.
* g10/pubkey-enc.c (get_it): Support Kyber decryption.

* g10/seskey.c (encode_session_key): Handle Kyber different from ECDH.
--

Having always the single byte in the packet data than to store and
retrieve it from an MPI is much easier.  Thus this patch changes the
original internal format.  With this chnages decryption of the slighly
modified test data works now. See the bug tracker for test data.

GnuPG-bug-id: 6815
2024-04-11 15:56:21 +02:00
Werner Koch 61717fb0a7
agent: Add more diagnostics to PQC decryption.
* agent/pkdecrypt.c (composite_pgp_kem_decrypt): Use %d for
correctness.  Add error diagnostics and one extra check.
--

GnuPG-bug-id: 7014
2024-04-11 15:48:16 +02:00
Werner Koch 869d1df270
indent: Re-indent a function
--
2024-04-11 11:33:37 +02:00
NIIBE Yutaka f2fd4f1a9e
agent: Rename the function using the word "composite"
* agent/pkdecrypt.c (composite_pgp_kem_decrypt): Rename.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-11 15:30:27 +09:00
NIIBE Yutaka 172d53d636
agent: Fix PQC decryption.
* agent/pkdecrypt.c (agent_hybrid_pgp_kem_decrypt): Change the format
of SEXP in the protocol for symmetric cipher algorithm identifier.

--

GnuPG-bug-id: 7014
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-11 15:30:16 +09:00
Werner Koch 6737e07a9b
doc: Move keyformat.txt to here.
--
2024-04-11 08:27:53 +02:00
Todd Zullinger via Gnupg-devel 87025e5da6
doc: Fix a few typos in agent/keyformat.txt
--

Signed-off-by: Todd Zullinger <tmz@pobox.com>
2024-04-11 08:17:20 +02:00
Werner Koch 84ddb24e30
gpg: Make Kyber creation more flexible.
* common/openpgp-oid.c (openpgp_is_curve_supported): Allow the
abbreviated curve name.
* g10/pkglue.c (pk_encrypt): Add debug output.
* g10/seskey.c (encode_session_key): Handle Kyber session key like
ECDH.  This is just a stub.
* g10/keygen.c (ecckey_from_sexp): Use the modern OID for cv25519.
(parse_key_parameter_part): Allow more Kyber variants.
--

Test by creating an ed25519 key and using

 gpg --quick-add-key --batch --passphrase ""  <fingerprint> <algo>

to create several subkeys.  Tested with ALGOs:

  kyber768
  kyber1024
  ky768_cv25519
  ky768_bp256
  kyber768_nistp256
  ky1024_cv448

All curves capable of encryption should work.

GnuPG-bug-id: 6815
2024-04-10 08:48:49 +02:00
NIIBE Yutaka c21237ac27
agent:kem: Externalize FIXED_INFO.
* agent/pkdecrypt.c (agent_hybrid_pgp_kem_decrypt): Don't hard code
the value of FIXED_INFO.  Get it from frontend.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-10 12:52:13 +09:00
NIIBE Yutaka aee6b1131b
common: Rename to kem.c from kmac.c.
* common/Makefile.am (common_sources): Fix to kem.c.
* common/kem.c: Rename.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-10 11:14:25 +09:00
NIIBE Yutaka 04b81ec236
common,agent: Factor out KEM functions into common/kem.c.
* common/util.h (compute_kmac256): Remove.
(gnupg_ecc_kem_kdf, gnupg_kem_combiner): New.
* common/kmac.c (compute_kmac256): Don't expose.
(gnupg_ecc_kem_kdf, gnupg_kem_combiner): New.
* agent/pkdecrypt.c (agent_hybrid_pgp_kem_decrypt): Use
gnupg_ecc_kem_kdf and gnupg_kem_combiner.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-10 11:09:29 +09:00
Werner Koch 52c4b09080
gpg: Some support to allow Kyber decryption.
* g10/call-agent.c (agent_pkdecrypt): Support dual keygrips and switch
to KEM mode.
* g10/ecdh.c (pk_ecdh_decrypt): Add an extra length check.
* g10/keyid.c (do_hash_public_key): Fix Kyber fingerprint computation.

* g10/mainproc.c (release_list): Free all 4 data elements.
(proc_pubkey_enc): Copy all 4 data elements.
* g10/misc.c (openpgp_pk_test_algo2): Map Kyber to KEM.

* g10/parse-packet.c (parse_pubkeyenc): Fix Kyber parser.
* g10/pubkey-enc.c (get_session_key): Allow Kyber.
(get_it): Support Kyber.
--

GnuPG-bug-id: 6815
2024-04-09 11:01:56 +02:00
Werner Koch 1a37f0080b
kbx: Support kyber in the blob parser.
* kbx/keybox-openpgp.c (keygrip_from_keyparm): Support Kyber.
(parse_key): Ditto.
--

GnuPG-bug-id: 6815
2024-04-09 11:01:56 +02:00
NIIBE Yutaka 3a344d6236
gpg: Allow no CRC24 checksum in armor.
* g10/armor.c (radix64_read): Detect the end of armor when
there is no CRC24 checksum.

--

GnuPG-bug-id: 7071
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-09 09:24:11 +09:00
Werner Koch f7a26aa8ad
kbx: Fix keyid search for mixed v4/v5 case.
* kbx/keybox-search.c (blob_cmp_fpr_part):  Reworked.
(has_short_kid, has_long_kid): Simplify.
--

The old code was too complicated and did not cope correctly a blob
having a mix of v5 and v4 keys.

Fixes-commit: 01329da8a7
GnuPG-bug-id: 5888
2024-04-08 20:32:47 +02:00
Werner Koch c5d7a332c8
gpg: Do not allow to accidently set the RENC usage.
* g10/keygen.c (print_key_flags): Print "RENC" if set.
(ask_key_flags_with_mask): Remove RENC from the possible set of
usages.  Add a direct way to set it iff the key is encryption capable.
--

This could be done by using "set your own capabilities" for an RSA
key.  In fact it was always set in this case.

GnuPG-bug-id: 7072
2024-04-05 16:18:34 +02:00
Werner Koch 03d53c88cc
gpg: Allow to create a Kyber key from keygrips.
* agent/cvt-openpgp.c (extract_private_key): Support Kyber algorithms.
* common/openpgp-oid.c (map_gcry_pk_to_openpgp): Map KEM to Kyber.
* common/sexputil.c (get_pk_algo_from_key): Increase buffer for use
with "kyber1024".
* g10/call-agent.c (agent_get_keyinfo): Fix warning.
* g10/keygen.c (do_create_from_keygrip): Support Kyber.
(ask_algo): Ditto.
--

To test create a standard key and the use --edit-key and "addkey" with
selection 13 and use the comma delimited keygrips.

GnuPG-bug-id: 7014
2024-04-05 16:16:53 +02:00
Werner Koch 68d9bc9c35
agent: Fix error handling of READKEY.
* agent/command.c (cmd_readkey): Jump to leave on reading error.
--

Fixes-commit: d7a3c455c5
2024-04-05 14:47:02 +02:00
Werner Koch 53c6b1e858
gpg: Support dual keygrips.
* g10/keyid.c (keygrip_from_pk): Add arg get_second to support dual
algos.  Implement for Kyber.
(hexkeygrip_from_pk): Extend for dual algos.
* g10/call-agent.c (agent_keytotpm): Bail out for dual algos.
(agent_keytocard): Ditto.
(agent_probe_secret_key): Handle dual algos.
(agent_probe_any_secret_key): Ditto.
(agent_get_keyinfo): Allow for dual algos but take only the first key.
* g10/export.c (do_export_one_keyblock): Bail out for dual algos.
--

This also adds some fixmes which we eventually need to address.

GnuPG-bug-id: 6815
2024-04-05 12:02:32 +02:00
Werner Koch ce8b25270b
agent: Make "PKDECRYPT --kem" with optional value work.
* agent/command.c (cmd_pkdecrypt): Fix comparison.

* agent/agent.h (enum kemids): Rename type and strip trailing comma.

* agent/pkdecrypt.c (agent_hybrid_pgp_kem_decrypt): Allow building
with Libgcrypt < 1.11
--

Eventually we should change the libgcrypt requirement in configure.
2024-04-05 11:22:38 +02:00
NIIBE Yutaka 131dd2a351
agent: Add initial support for hybrid ECC+PQC decryption with KEM.
* agent/agent.h (enum kemid): New.
(agent_kem_decrypt): New.
* agent/command.c (cmd_pkdecrypt): Support --kem option to call
agent_kem_decrypt.
* agent/pkdecrypt.c (reverse_buffer): New.
(agent_hybrid_pgp_kem_decrypt): New.
(agent_kem_decrypt): New.

--

Now, it only supports X25519 + ML-KEM.

GnuPG-bug-id: 7014
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-05 14:17:25 +09:00
Werner Koch 97f5159495
gpg: Initial support for generating Kyber subkeys.
* common/openpgpdefs.h (PUBKEY_ALGO_KY768_25519): Remove.
(PUBKEY_ALGO_KY1024_448): Remove.
(PUBKEY_ALGO_KYBER): New.  Use them everywhere instead of the removed.

* g10/build-packet.c (gpg_mpi_write_nohdr): Rename to
(gpg_mpi_write_opaque_nohdr): this.  Change callers.
(gpg_mpi_write_opaque_32): New.
(do_key): Support Kyber keys using the revised format.
* g10/gpg.h (MAX_EXTERN_KEYPARM_BITS): New.
* g10/parse-packet.c (read_octet_string): Add arg nbytes so support
reading with a length prefix.  Adjust callers.
(parse_key): Parse Kyber public keys.
* g10/misc.c (pubkey_get_npkey): Support Kyber.
(pubkey_get_nskey): Ditto.

* g10/keyid.c (pubkey_string): Support dual algorithms.
(do_hash_public_key): Support Kyber.
(nbits_from_pk): Ditto.
(keygrip_from_pk): Return the Kyber part for the ECC+Kyber dual algo.

* g10/keygen.c (struct common_gen_cb_parm_s): Add genkey_result2.
Note that this callback is not yet used.
(ecckey_from_sexp): Add optional arg sexp2 and use it for Kyber.
Change callers.
(ecckey_from_sexp): Do not leak LIST in case of an error.
(common_gen): Add arg keyparms2, change callers, and support Kyber.
(gen_kyber): New.
(get_keysize_range): Support Kyber.
(fixup_keysize): Simplify and support Kyber.
(do_create): Handle Kyber.
(parse_key_parameter_part): Remove algo strings "ky768" and "ky1024"
and add a generic "kyber" with default parameters.
--

This uses a revised format which is more aligned with the usual
OpenPGP structure.  A lot of things are still missing.  For example
support for handling two keygrips and checking both of them in a -K
listing.  There is also only ky768_bp384 as fixed algorithm for now.
No passphrase for the Kyber part of the dual algorithm is on purpose.

A test was done using

  gpg --quick-gen-key pqc1 nistp256

and then running

  gpg -v --quick-add-key <fingerprint> kyber

which creates a v5 subkey on a v4 primary key.  A second test using

  gpg --quick-gen-key pqc2 Ed448

followed by a --quick-add-key created a v5 key with a v5 subkey.

GnuPG-bug-id: 6815
2024-04-03 18:01:11 +02:00
Werner Koch 6c1dd3afd1
common: Extend openpgp_oid_to_curve to return an abbreviated name.
* common/openpgp-oid.c (oidtable): Add column "abbr" and set them for
Brainpool.
(openpgp_oid_to_curve): Rename arg "canon" to "mode" and implement
mode 2.
--

For dual algorithms (PQC) we need shorter versions of brainpool to
avoid names which otherwise might be capped when printed.
2024-04-03 14:13:57 +02:00
Werner Koch 4b981e415f
tests: Add a sample PDF with a signature
--
2024-04-03 09:52:14 +02:00
Werner Koch fa33b18940
common: Allow building with libgcrypt 1.10 for now.
* common/kmac.c (compute_kmac256): Return an error for older gcrypt
versions.
--

Except for the new KEM module there is no hard requirement for
libgcrypt 1.11 *yet*.
2024-04-03 09:43:37 +02:00
NIIBE Yutaka c69363e8c7
agent: Add --another option for hybrid crypto.
* agent/agent.h (struct server_control_s): Add have_keygrip1.
* agent/command.c (reset_notify): Clear have_keygrip1 field.
(cmd_havekey): Add --another option handling.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-01 14:38:51 +09:00
NIIBE Yutaka 1fa24e2841
common: Add KMAC.
* common/Makefile.am (common_sources): Add kmac.c.
* common/kmac.c: New.
* common/util.h (compute_kmac256): New.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-03-29 15:26:42 +09:00
Werner Koch 571a768ac6
gpgsm: Allow to add extensions at the --gen-key prompt.
* sm/certreqgen-ui.c (gpgsm_gencertreq_tty): Add a prompt for
extensions.
--

An example for an extension would be extKeyUsage for authentication:

   2.5.29.37 n 301406082B0601050507030206082B06010505070301
2024-03-27 12:12:52 +01:00
NIIBE Yutaka 984a0c6982
scd:openpgp: Fix data_objects specification for F9 and FA.
* scd/app-openpgp.c (data_objects): These are constructed objects.

--

GnuPG-bug-id: 7058
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-03-27 10:27:04 +09:00
Werner Koch f9919bcc48
gpg,gpgsm: New option --disable-fd-translation.
* common/sysutils.c (no_translate_sys2libc_fd) [W32]: New global.
(disable_translate_sys2libc_fd): New.
(translate_sys2libc_fd): Make static and cobuild only for Windows.
(translate_sys2libc_fd_int): Use no_translate_sys2libc_fd flag.

* g10/gpg.c, sm/gpgsm.c (oDisableFdTranslation): New const.
(opts): Add option "disable-fd-translation".
(main): Set option.
--

GnuPG-bug-id: 7060
2024-03-26 15:46:56 +01:00
Werner Koch cec1fde1bc
scd: Add new OpenPGP vendor
--
2024-03-26 14:57:52 +01:00
Werner Koch a0bfbdaaa2
Allow installation with a gpgconf.ctl changed homedir.
* common/homedir.c (gpgconf_ctl): Add field "gnupg".
(parse_gpgconf_ctl): Support keyword "gnupg".
(my_gnupg_dirname): New.
(my_fixed_default_homedir): New.
(gnupg_registry_dir): New.
(standard_homedir): Use my_gnupg_dirname and my_fixed_default_homedir.
(default_homedir): Use gnupg_registry_dir and
my_fixed_default_homedir.
(_gnupg_socketdir_internal): Use my_gnupg_dirname.  Increase size of
prefixbuffer.
(gnupg_sysconfdir): Use my_gnupg_dirname.
* tools/gpgconf.c (list_dirs): Use gnupg_registry_dir.
(show_other_registry_entries): Ditto.
--

This will be useful to install versions of GnuPG VS-Desktop and GnuPG
Desktop in addition to a standard GnuPG version.  Only basic tests on
Unix done; Windows testing is still outstanding.

GnuPG-bug-id: 7040
2024-03-21 17:41:10 +01:00
Werner Koch fb3fe38d28
common: Use a common gpgconf.ctl parser for Unix and Windows.
* common/homedir.c (gpgconf_ctl): new struct.
(string_is_true): New.
(parse_gpgconf_ctl): New.  Based on the former code in unix_rootdir.
(check_portable_app): Use parse_gpgconf_ctl and the new struct.
(unix_rootdir): Ditto.
--

This is a unification of the gpgconf.ctl mechanism.  For backward
compatibility we need to keep the empty (or actually only comments)
method as used formerly under Windows.  Iff one really wants a
portable application the new portable keyword should be used, though.

Noet that the Windows portable stuff has not been tested for quite
some time.
2024-03-21 15:47:43 +01:00
Werner Koch 50e81ad38d
gpg: Make sure a DECRYPTION_OKAY is never issued for a bad OCB tag.
* g10/mainproc.c (proc_encrypted): Force a decryption failure if any
error has been seen.
* g10/decrypt-data.c (aead_checktag): Issue an ERROR line.
--

GnuPG-bug-id: 7042

Note that gpg in any case returns a failure exit code but due to
double forking GPGME would not see it.
2024-03-14 21:41:48 +01:00
Werner Koch f78501c545
gpg: new list-option store-x509-notations.
* g10/options.h (LIST_STORE_X509_NOTATIONS): New.
* g10/gpg.c (parse_list_options): Add "store-x509-notations".
* g10/keylist.c (print_x509_notations): Add arg PK and code to write a
file.
(list_signature_print): Add arg lastpk and handle new option.
(list_keyblock_print): Track last key or subkey and pass to
list_signature_print.
2024-03-14 20:58:01 +01:00
Werner Koch 14c1b73093
gpg: new list-option show-x509-notations
* g10/gpg.c (parse_list_options): Add new option.
* g10/options.h (LIST_SHOW_X509_NOTATIONS): New.
* g10/build-packet.c (search_sig_notations): New.
* g10/keylist.c (print_x509_notations): New.
(list_signature_print): Use macros for the sig classes.  Call
print_x509_notations.
(list_keyblock_print): Call list_signature_print if x509 notation
printing is enabled.
2024-03-12 18:01:24 +01:00
Werner Koch 81536535f8
card: Use xstrdup for module names.
--
2024-03-12 16:04:19 +01:00
Werner Koch 4485930f9f
Merge branch 'STABLE-BRANCH-2-4'
--
Resolved conflicts:
	NEWS
	common/exechelp-w32.c
	configure.ac
2024-03-12 16:00:55 +01:00
Werner Koch 609b1ec0c6
Post release updates
--
2024-03-07 15:10:47 +01:00
Werner Koch cbff323b3b
Release 2.4.5 2024-03-07 14:03:25 +01:00
Werner Koch 348de4a829
po: msgmerge
--
2024-03-07 14:01:59 +01:00
Werner Koch 3ffcd533d4
po: Fix a fuzzy in the German, Polish and Japanese translation
--
2024-03-07 14:01:22 +01:00
Werner Koch 09431d1762
scd: Improve code reability of ccid-driver.c
* scd/ccid-driver.c (my_npth_unprotect, my_npth_protect): New.
Replace all direct uses by these wrappers.
2024-03-07 13:44:30 +01:00
Werner Koch 1682ca9f01
scd: Add support for ACR-122U
* scd/ccid-driver.h (VENDOR_ACR, ACR_122U): New.
* scd/ccid-driver.c (ccid_open_usb_reader): Do not call
libsub_set_interface_alt_setting for this reader.
--

Co-authored-by: markus.montkowski@gnupg.com
2024-03-07 13:44:00 +01:00
Werner Koch a1ea3b13e0
scd: Let the CCID module auto detach the kernel driver.
* scd/ccid-driver.c (ccid_open_usb_reader): Call
libusb_set_auto_detach_kernel_driver.

* scd/scdaemon.c (oCompatibilityFlags): New.
(opts): Add option "compatibility-flags".
(compatibility_flags): New.
(main): Parse flags.
* scd/scdaemon.h (opt): Add field compat_flags.
(COMPAT_CCID_NO_AUTO_DETACH): New.
2024-03-07 13:21:43 +01:00
Werner Koch 79d0e52b2d
gpg: Fix a possible segv due to an uninitialized gcrypt context.
* g10/sign.c (sign_symencrypt_file): Initialize MD for the error case.
--

Reported-by: Falko Strenzke
Fixes-commit: 1ddd69935d
in the not yet released master branch.
2024-03-06 15:49:51 +01:00
Werner Koch 00b877ecda
doc: Typo fix in comment
--
2024-03-06 11:54:33 +01:00
Werner Koch 37cc255e49
wks: Make gpg-wks-client --mirror work w/o args.
* tools/gpg-wks-client.c (mirror_one_key): Test for no domain
specified.
--

The code did not really work if no domain was given.  It worked but
filtered out all keys so that no key was actually exported.
2024-03-06 10:00:37 +01:00
Werner Koch 345794cfe6
gpg: Fix mixed invocation with --trusted-keys and --no-options.
* g10/trustdb.c: Move a function and some definitions around.
(user_utk_list): Rename to trusted_key_list.  Change all users.
(any_trusted_key_seen): New.
(tdb_register_trusted_key): Set it here.  Handle the new value "none".
(verify_own_keys): Do not delete a trusted key from the trustdb if a
trusted-key option was not used.
--

GnuPG-bug-id: 7025
2024-03-04 14:58:45 +01:00
Werner Koch 36a3550bff
wks: Add option --realclean to gpg-wks-client.
* tools/gpg-wks-client.c (oRealClean): New.
(opts): Add "realclean".
(parse_arguments): Implement.
(main): Take a copy of the module name to fix bad assignment from a
former patch.
* tools/gpg-wks-server.c (main): Ditto.
* tools/gpg-wks.h (opt): Add field realclean.
* tools/wks-util.c (wks_get_key): Call gpg with export-realclean
depending on the new option.
--

The default for gpg-wks-client is to install keys with all valid key
signatures.  The new option will eventually allow to install the keys
only with key signatures done by trusted-keys.  Also the export-option
is in gpg, it requires one more gpg patch to make it actually work.
2024-03-04 14:28:48 +01:00
Werner Koch 74e4dd3668
gpg: Prepare for a new export option export-realclean.
* g10/options.h (EXPORT_REALCLEAN): New.  Also re-assign other values
to keep them more in sync with the corresponding import values.
* g10/export.c (parse_export_options): Add "export-realclean".
(do_export_stream): Call clean_all_uids directly with the options
arg.
* g10/import.c (import_one_real): Change for direct use of options in
clean_all_uids.
* g10/key-clean.c (is_trusted_key_sig): New.  Stub for now.
(clean_sigs_from_uid): Re-purpose self_only to a general options arg.
Implement EXPORT_REALCLEAN code path.
(clean_one_uid): Re-purpose self_only to a general options arg.
(clean_all_uids): Ditto.
* g10/keyedit.c (keyedit_menu): Use EXPORT_MINIMAL instead of a simple
flag.
(menu_clean): Re-purpose self_only to a general options arg.

* g10/keyid.c (fpr20_from_pk): Factor code out to ....
(fpr20_from_fpr): new.  Remove useless case for ARRAY being NULL.
* g10/tdbio.c (tdbio_search_trust_byfpr): Add arg fprlen and use
fpr20_from_fpr if needed.
(tdbio_search_trust_bypk): Pass 20 for the fingerprint length.
--

Note that this code has no function yet.  Another patch will follow to
extract the trusted-keys flag from the trustdb.
2024-03-04 14:22:42 +01:00
Werner Koch 233bf39323
build: Extend getswdb.sh to allow a verified download
--
2024-02-29 15:35:27 +01:00
Werner Koch c27e5be50b
build: Make getswdb.sh usable outside the GniPG tree.
--
2024-02-29 10:21:33 +01:00
Werner Koch dcab895e4c
gpg: Emit status lines for errors in the compression layer.
* g10/compress-bz2.c: Replace all log_fatal by log_error,
write_status_error, and g10_exit.
(do_uncompress): Ditto.
--

This gives gpgme a better way to detect corrupted data in the
compression layer.
GnuPG-bug-id: 6977
2024-02-27 11:33:21 +01:00
Werner Koch 962058f704
Allow tilde expansion for the foo-program options.
* agent/gpg-agent.c (parse_rereadable_options): Use make_filename_try
for opt.pinentry_program.  Change definition accordingly.
* g10/gpg.c (main): Use make_filename for agent_program,
dirmngr_program, and keyboxd_program. Change definition accordingly.
* sm/gpgsm.c (main): Ditto.
* tools/gpg-card.c (parse_arguments): Ditto.
* tools/gpg-connect-agent.c (main): Ditto.
* tools/gpg-wks-client.c (parse_arguments): Likewise.  Do it also for
option --output.
(process_confirmation_request): Print a note for a successful sent.
--

GnuPG-bug-id: 7017
2024-02-27 10:36:22 +01:00
Werner Koch adf4db6e20
agent: Allow GET_PASSPHRASE in restricted mode.
* agent/command.c (cmd_get_passphrase): Allow use in restricted mode
but ignore the cacheid.
--

The use case is symmetric encryption via the extra-socket.  To avoid
that the gpg running on the server has access to the cache we set the
cache id to NULL so that the cache is not used at all.
2024-02-25 16:03:54 +01:00
Werner Koch 40227e42ea
doc: Document the "grp" record in colon listings.
--
2024-02-22 17:05:04 +01:00
Werner Koch 2372f6a403
gpg: Fix gpg_mpi_write for the unused opaque case.
* g10/build-packet.c (gpg_mpi_write): Take care of the fact that
get_opaque already returns a bit-exact value.
--

Fixes-commit: ab17f7b6c3
Reported-by: Falko Strenzke <falko.strenzke@mtg.de>
2024-02-21 15:55:14 +01:00
Werner Koch a09157ccb2
wks: Allow command style args for gpg-wks-client.
* tools/gpg-wks-client.c (wrong_args): Take two args.  Change all
callers.
(main): Pass ARGPARSE_FLAG_COMMAND for recent gpgrt version.
--

This requires gpgrt 1.48.  Of course "gpg-wks-client --create ..."
continues to work.
2024-02-21 14:07:06 +01:00
Werner Koch 95bc592ab5
g13: Allow command line style "g13 mount foo".
* g13/g13.c (main): Set flag ARGPARSE_FLAG_COMMAND.
--

This requires gpgrt 1.48.  Of course "g13 --mount foo" continues to
work.
2024-02-20 11:40:49 +01:00
Mario Haustein 3aa02027cd
scd:p15: Fix typo in a comment 2024-02-20 10:34:39 +01:00
Mario Haustein 557f29d2c1
scd:p15: Add ECC support for D-Trust Card 4.1/4.4
* scd/app-p15.c (do_sign): Add MSE RESTORE parameters for D-Trust ECC
cards.
(do_decipher): Ditto.
2024-02-20 10:32:08 +01:00
Werner Koch 1e496cf2e5
scd:p15: Take derive usage into account for decryption (2).
* scd/app-p15.c (do_getattr): Yet another palce to fix.
--
GnuPG-bug-id: 7000
Co-authored-by: Mario Haustein <mario.haustein@hrz.tu-chemnitz.de>
2024-02-20 10:29:25 +01:00
Werner Koch 3341017ff1
scd:p15: Handle duplicate certificate ids.
* scd/app-p15.c (struct app_local_s): Add field cdf_dup_counter.
(objid_in_cdflist_p): New.
(read_p15_info): Clear the counter.
(read_ef_cdf): Detect and fix duplicate IDs.
--

GnuPG-bug-id: 7001
Reported-by: Mario Haustein <mario.haustein@hrz.tu-chemnitz.de>
2024-02-20 09:17:38 +01:00
Werner Koch ad4bc3e04d
scd:p15: Take derive usage into account for decryption.
* scd/app-p15.c (set_usage_string): Map usageflags.derive also to 'e'.
(do_auth): Allow usageflags.sign_recover.
(do_decipher): Allow usageflags.derive.
(do_with_keygrip): Take usageflags.derive into account.
(do_gettatr): Ditto.
(do_decipher): Take a missing AODF for authentication not needed.
--

This is required for D-Trust ECC cards.

The AODF thing is unrelated but seems to be a good idea.

GnuPG-bug-id: 7000
2024-02-20 09:17:38 +01:00
NIIBE Yutaka 2810b93464
dirmngr: Fix keep-alive flag handling.
* dirmngr/http.c (run_proxy_connect): Set KEEP_ALIVE if not Basic
Authentication.  Fix resource leak of FP_WRITE.

--

GnuPG-bug-id: 6997
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-02-16 16:24:26 +09:00
NIIBE Yutaka 848546b05a
dirmngr: Fix the regression of use of proxy for TLS connection.
* dirmngr/http.c (run_proxy_connect): Don't set keep_alive, since it
causes resource leak of FP_WRITE.
Don't try to read response body to fix the hang.

--

GnuPG-bug-id: 6997
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-02-16 11:38:57 +09:00
Werner Koch 0370678536
speedo: Add config variable for the timestamp service.
--
2024-02-15 14:53:28 +01:00
NIIBE Yutaka 04cbc3074a
dirmngr: Fix proxy with TLS.
* dirmngr/http.c (proxy_get_token, run_proxy_connect): Always
available regardless of USE_TLS.
(run_proxy_connect): Use log_debug_string.
(send_request): Remove USE_TLS.

--

Since the commit of

	1009e4e5f7

Building with TLS library is mandatory.

GnuPG-bug-id: 6997
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-02-15 15:38:34 +09:00
NIIBE Yutaka 874918ab91
common,dirmngr:w32: Add include files.
* common/dynload.h: Include windows.h.  Don't define RTLD_LAZY, if
already defined.
* common/init.c: Include wctype.h.
* dirmngr/certcache.c: Include wincrypt.h.
* dirmngr/dns-stuff.c: Include ws2tcpip.h.

--

GnuPG-bug-id: 5894
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-02-15 14:40:33 +09:00
NIIBE Yutaka 27f66148f7
dirmngr:w32: Add include files.
* dirmngr/ks-engine-ldap.c: Include winldap.h and winber.h.

--

Definition of ber_free is in winber.h.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-02-15 14:38:10 +09:00
Werner Koch 302afcb6f6
gpg: Add option --assert-pubkey_algo.
* g10/keyid.c (parse_one_algo_string): New.
(compare_pubkey_string_part): New.
(compare_pubkey_string): New.
* g10/verify.c (check_assert_signer_list): New.
* g10/mainproc.c (check_sig_and_print): Call check_assert_pubkey_algo.
* g10/options.h (opt): Add field assert_pubkey_algos.
* g10/gpg.c (oAssertPubkeyAlgo): New.
(opts): Add "--assert-pubkey_algo".
(assert_pubkey_algo_false): New.
(main): Parse option.
(g10_exit): Reorder RC modifications.  Check assert_pubkey_algo_false.
* common/status.h (ASSERT_PUBKEY_ALGOS): new.
* common/t-support.h (LEAN_T_SUPPORT): Use a simplified version if
this macro is set.

* g10/gpgv.c (oAssertPubkeyAlgo): New.
(opts): Add "--assert-pubkey_algo".
(assert_pubkey_algo_false): New.
(main): Parse option.
(g10_exit): Check assert_pubkey_algo_false.

* g10/t-keyid.c: New.
* g10/Makefile.am: Add t-keyid.
* g10/test-stubs.c: Add assert_pubkey_algos and assert_signer_list and
remove from other tests.
(check_assert_signer_list): Ditto.
(check_assert_pubkey_algo): Ditto.
--

GnuPG-bug-id: 6946
2024-02-10 14:26:55 +01:00
Werner Koch 5842eee805
doc: Suggest the use of a fingerprint for --default-key.
--

GnuPG-bug-id: 6975
2024-02-05 08:53:06 +01:00
Werner Koch e5f24218fc
doc: Improve warning for --use-embedded-filename.
--

GnuPG-bug-id: 6972
2024-02-05 08:42:56 +01:00
Werner Koch 214d3ffe0f
gpgsm: Increase salt size in pkcs#12 parser.
* sm/minip12.c (parse_bag_encrypted_data): Need 32 bytes.
--

GnuPG-bug-id: 6757
2024-02-05 08:00:20 +01:00
Ángel González 375c3a238a
gpgsm: cleanup on error paths
* sm/minip12.c (p12_parse): set err on the different error paths

--

GnuPG-bug-id: 6973
Fixes-commit: 101433dfb4
Signed-off-by: Ángel González <angel@pgp.16bits.net>
2024-02-05 07:54:14 +01:00
Werner Koch 40b85d8e8c
scd:openpgp: Allow PIN length of 6 also with a reset code.
* scd/app-openpgp.c (do_change_pin): Fix PIN length check.  Add "R"
flag to the reset code prompt.
--

When using the reset code it was not possible to set a PIN of length
6.  The "R" flags fixes a funny prompt.

Fixes-commit: efe325ffdf
scd:openpgp: Allow PIN length of 6 also with a reset code.

* scd/app-openpgp.c (do_change_pin): Fix PIN length check.  Add "R"
flag to the reset code prompt.
--

When using the reset code it was not possible to set a PIN of length
6.  The "R" flags fixes a funny prompt.

Fixes-commit: 2376cdff13
2024-01-30 15:58:14 +01:00
Andre Heinecke d6dedda3f2
w32, msi: Fix directory of gpg-card, add keyboxd
* build-aux/speedo/w32/wixlib.wxs: Fix gpg-card directory id.
Add keyboxd.
2024-01-30 10:20:43 +01:00
Jakub Bogusz 300c9eeace
po: update Polish translation 2024-01-29 10:59:13 +01:00
Werner Koch 03207f62e8
gpg: Minor code cleanup for fingerprint computation.
* g10/keyid.c (do_hash_public_key): Simplify code for clarity.
2024-01-29 10:30:51 +01:00
Werner Koch ae0a755e0d
gpg: Hide --textmode from the help output.
--
2024-01-29 09:26:26 +01:00
Werner Koch 78eae9ffe8
doc: Mark --textmode as legacy option.
--
2024-01-29 09:24:19 +01:00
Werner Koch 2ed1f68b48
doc: Fix spelling errors found by lintian.
--

Reported-by: Andreas Metzler <ametzler@debian.org>
2024-01-29 09:16:21 +01:00
Werner Koch 97b2837653
speedo: Improve parsing of the ~./.gnupg-autogen.rc
--

We now allow spaces around the variable name and the value.
2024-01-26 16:01:06 +01:00
Werner Koch 4dc09bc5e7
dirmngr: For CRL issuer verification trust the system's root CA.
* dirmngr/crlcache.c (crl_parse_insert): Add
VALIDATE_FLAG_TRUST_SYSTEM.
--

GnuPG-bug-id: 6963
2024-01-26 13:14:35 +01:00
Werner Koch eaf6a7ab87
common,w32: Fix use of GNUPG_SPAWN_KEEP_STDERR.
* common/exechelp-w32.c (gnupg_spawn_process): Fix macro.
--

Fixes-commit: 6d6438a361
GnuPG-bug-id: 6961
2024-01-26 10:29:08 +01:00
Werner Koch dfa60c09f5
Merge branch 'STABLE-BRANCH-2-4'
--
Fixed conflicts:
	NEWS
	configure.ac
	doc/gpg.texi
2024-01-26 09:41:00 +01:00
NIIBE Yutaka af6ac2ac02
gpg: Clean up pk_ecdh_decrypt function.
* g10/ecdh.c (pk_ecdh_decrypt): Allocate just the right size of memory
for the session key, simplifying the decrypt process.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-01-26 14:13:01 +09:00
Werner Koch 367ae86019
Post release updates
--
2024-01-25 11:30:37 +01:00
NIIBE Yutaka ccfbb9ebdf
kbx: Have threads monitoring socket takeover and homedir if no inotify.
* kbx/keyboxd.c (CHECK_PROBLEMS_INTERVAL): New.
(have_homedir_inotify): Remove the global.
[HAVE_W32_SYSTEM] (create_an_event): New.
(handle_tick): Remove.
(handle_signal): Add handling SIGCONT.
(keyboxd_kick_the_loop): New.
(handle_connections): Spawn check_own_socket_thread and
check_others_thread if no inotify.
(check_own_socket_thread, check_others_thread): New.

--

This change follows the change of gpg-agent.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-01-24 13:45:49 +09:00
NIIBE Yutaka 6ddaf2be9f
common: Remove t-b64.c.
* common/Makefile.am (module_tests): Remove t-b64.
(t_b64_LDADD): Remove.
* common/t-b64.c: Remove.

--

GnuPG-bug-id: 6734
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-12-26 15:07:44 +09:00
NIIBE Yutaka 7cde533ce8
agent,kbx: Fix reliable_homedir_inotify (2/2).
* agent/gpg-agent.c (main): The value of reliable_homedir_inotify
doesn't not related to nodetach, and it's only zero in the specific
condition.
* kbx/keyboxd.c (handle_connections): Remove the last argument.
(main): Remove reliable_homedir_inotify, as it's always one.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-12-26 13:29:49 +09:00
NIIBE Yutaka c44f0bc91e
agent,kbx: Fix reliable_homedir_inotify (1/2).
* agent/gpg-agent.c (reliable_homedir_inotify): Remove the global.
(handle_connections): Add reliable_homedir_inotify as an arg.
Don't call gnupg_inotify_watch_delete_self when it's not reliable.
(check_others_thread): No check of reliable_homedir_inotify repeatedly
in the loop.
* kbx/keyboxd.c (reliable_homedir_inotify): Remove the global.
(handle_connections): Add reliable_homedir_inotify as an arg.
(handle_tick): No check of reliable_homedir_inotify in the loop.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-12-26 13:29:40 +09:00
Werner Koch 2764ee309a
Merge branch 'STABLE-BRANCH-2-4'
--

Fixed conflicts in
        NEWS
	g10/encrypt.c
	sm/encrypt.c
	sm/sign.c
2023-12-22 13:45:02 +01:00
Werner Koch 853f36e596
Register DCO for Mario Haustein
--
2023-12-21 11:50:16 +01:00
NIIBE Yutaka 4dd4e9d2f1
agent: Fix homedir check wrt --disable-check-own-socket option.
* agent/gpg-agent.c (handle_connections): Don't disable use of inotify
when it has the --disable-check-own-socket option.

--

Before the fix, it checks the homedir using the gnupg_stat function
when --disable-check-own-socket is enabled, without trying use of
inotify.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-12-20 16:13:49 +09:00
NIIBE Yutaka 4e94b004a6
scd: Debug output is only enabled with an option.
* scd/command.c (pin_cb): Check if DBG_IPC for log_debug.
(send_client_notifications): Check opt.verbose to output a message.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-12-18 11:25:01 +09:00
NIIBE Yutaka 37fa36a329
doc: Fix description of scdaemon for --disable-ccid.
--

Cherry-picked from 2.4 branch of the commit:

	6b93b92111

GnuPG-bug-id: 6871
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-12-12 14:30:59 +09:00
Ahelenia Ziemiańska 1ded50dd5b
po: Fix quotes in Polish Translation.
--

Cherry-pick from 2.4 commit of:
	fa677a37ce

Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
2023-12-07 12:01:25 +09:00
Daniel Cerqueira 548d4aad5f
po: Update Portuguese Translation.
--

Cherry-picked from 2.4 branch of commit:
	a14f73a192

This commit log (with no ChangeLog entry) is written by gniibe,
following the practice; Translation update don't need a ChangeLog
entry in a commit log.

Signed-off-by: Daniel Cerqueira <dan.git@brilhante.top>
2023-12-01 15:23:49 +09:00
NIIBE Yutaka 42ee841976
doc: Update for gpgv.
--

GnuPG-bug-id: 6810
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-16 13:31:42 +09:00
Max-Julian Pogner 2600047470
gpgv: Update used keyrings in doc FILES section
* doc/gpgv.texi: Explicitely list all searched default keyrings in the
  FILES section.
* doc/gpgv.texi: use ${GNUPGHOME} placeholder to be extra precise.
2023-11-16 11:46:22 +09:00
Werner Koch 6fab7b075a
gpg: Implement a parser for Kyber encrypted packets.
* g10/misc.c (pubkey_get_nenc): Add ky768 and ky1024 values.
* g10/parse-packet.c (read_octet_string): New.
(read_size_body): Rename to ...
(read_sized_octet_string): this and change args to update-able PKTLEN.
(parse_pubkeyenc): Split general parsing loop for easier reading.
Implement parser for the Kyber algorithms.
--

Take care: this has not been tested at all, it merely passes the
regression test for the other algos.

Kyber is also known as ML-KEM in FIPS-203.

The list mode is slighly changed: In case of a parsing error no data
is printed - before that already parsed data was printed.

GnuPG-bug-id: 6815
2023-11-13 16:13:30 +01:00
NIIBE Yutaka ec1446f944
gpg,sm: Set confidential in assuan communication for password.
* g10/call-agent.c (default_inq_cb): Call assuan_begin_confidential
and assuan_end_confidential.
* sm/call-agent.c (default_inq_cb): Likewise.

--

GnuPG-bug-id: 6654
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-09 13:36:12 +09:00
NIIBE Yutaka 64f5f7b74e
gpg,tools: Handle GPG_ERR_PIN_BLOCKED and GPG_ERR_NO_RESET_CODE.
* g10/card-util.c (write_sc_op_status): Emit 3 and 4 in status line.
* tools/card-call-scd.c (status_sc_op_failure): Likewise.

--

GnuPG-bug-id: 6425
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-08 13:41:16 +09:00
NIIBE Yutaka 65607fb81d
tools:gpg-card: Fix an error code for Reset Code.
* tools/gpg-card.c (cmd_unblock): Use GPG_ERR_NO_RESET_CODE.

--

GnuPG-bug-id: 6425
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-08 13:31:55 +09:00
NIIBE Yutaka e6b3d53db3
scd: Return GPG_ERR_PIN_BLOCKED when it's blocked.
* scd/app-openpgp.c (build_enter_admin_pin_prompt): Fix to use
GPG_ERR_PIN_BLOCKED.
(check_pin): Likewise.

--

GnuPG-bug-id: 6425
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-08 11:44:06 +09:00
Werner Koch 387ee7dcbd
Merge branch 'STABLE-BRANCH-2-4'
* common/b64dec.c (b64decode): Move to ...
* common/miscellaneous.c: here.

* common/t-b64.c: Re-inroduce and keep only the b64decode test code.
2023-11-07 20:38:27 +01:00
NIIBE Yutaka 337de21f4b
doc: Use the em dash to mark a break in a sentence.
--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-07 13:55:29 +09:00
NIIBE Yutaka 00da0e9f93
doc: Remove stray .RE in doc/gpgsm.texi.
--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-06 14:47:21 +09:00
NIIBE Yutaka c2812a9bbc
doc: Fix to avoid using en-dash for command options.
--

GnuPG-bug-id: 6746
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-02 15:05:19 +09:00
Andre Heinecke 05ef8c0cc0
g10: Fix uninitalized variable use in sign_file
* g10/sign.c (sign_file): Initialize gcry_md_hd_t to NULL.

--
There are several jumps to leave before gcry_md_open is called so
md should be initialized to NULL to avoid calling gcry_md_close
on an uninitalized variable.

GnuPG-Bug-Id: T6780
2023-10-28 14:20:31 +02:00
NIIBE Yutaka 16b6b77532
Minor style fixes.
--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-05 14:00:46 +09:00
NIIBE Yutaka 227b3b14f4
tests:tpm2dtests: Modify tests with SWTPM and relax the condition.
* configure.ac (SWTPM_IOCTL): Remove.
(TEST_LIBTSS): Fix the condition.
* tests/tpm2dtests/Makefile.am (TESTS_ENVIRONMENT): Remove
SWTPM_IOCTL.
* tests/tpm2dtests/start_sw_tpm.sh: Add --flags to invoke SWTPM,
not requiring SWTPM_IOCTL and TSSSTARTUP any more.

--

GnuPG-bug-id: 6052
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-05 10:21:35 +09:00
NIIBE Yutaka 98dd6f7af6
tests:tpm2dtests: Fix tests with SWTPM.
* configure.ac (TEST_LIBTSS): Fix the condition with SWTPM.
* tests/tpm2dtests/start_sw_tpm.sh: Use --daemon and --pid
to run SWTPM.

--

GnuPG-bug-id: 6052
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-04 18:30:33 +09:00
NIIBE Yutaka 08e529fa7c
agent: Fix agent_update_private_key.
* agent/findkey.c (agent_update_private_key): Check FNAME0.

--

Fixes-commit: a216e9c028
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-04 10:25:30 +09:00
NIIBE Yutaka f2ca727978
build: Simplify detecting a TPM emulator.
* configure.ac (TPMSERVER): Don't supply hard-coded path.
(SWTPM, SWTPM_IOCTL, TSSSTARTUP): Likewise.

--

Having hard-coded path has bad side effect; It may not be detected
even if it's available with PATH.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-03 16:55:02 +09:00
NIIBE Yutaka 25c84ffd10
tools: Add TPM2DAEMON_SOCK_NAME for --remove-socketdir.
* tools/gpgconf.c (main): Care about tpm2d.  Emit correct ERR.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-03 16:54:19 +09:00
NIIBE Yutaka 321f9c0a3f
tests:tpm2dtests: Fix tests with TPM2D.
* tests/tpm2dtests/Makefile.am (TESTS_ENVIRONMENT): Fix.
* tests/tpm2dtests/all-tests.scm: Follow the change of gpgscm.
* tests/tpm2dtests/run-tests.scm: Likewise.

--

GnuPG-bug-id: 6052
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-03 11:53:00 +09:00
NIIBE Yutaka 4206d89003
tests:gpgscm: Fix process select loop.
* tests/gpgscm/ffi.c (do_process_spawn_io): Clear READ_FDSET in the
loop.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-03 11:44:11 +09:00
NIIBE Yutaka 78afc209cc
tpm2d: Fix call to assuan_control.
* tpm2d/tpm2daemon.c (main): Use ASSUAN_CONTROL_REINIT_SYSCALL_CLAMP.

--

Fixes-commit: 9e4d522239
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-10-02 10:32:04 +09:00
NIIBE Yutaka 1da40db03e
tpm2d: Check SWTPM environment variable for swtpm support.
* tpm2d/intel-tss.h (TSS_Create): Check SWTPM.

--

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
2023-09-28 13:26:52 +09:00
NIIBE Yutaka eda3997b43
agent: fix tpm2d keytotpm handling
* agent/divert-tpm2.c (agent_write_tpm2_shadow_key): Call
agent_delete_key before agent_write_private_key.  Recover
from an error.

--

Fixes-commit: a1015bf2fc
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
2023-09-28 11:59:14 +09:00
NIIBE Yutaka 459bd577fc
agent,common,gpg: Use unsigned int for 1-bit field.
* agent/trustlist.c (struct trustitem_s): Use unsigned int.
* common/audit.c (struct log_item_s): Likewise.
* g10/packet.h (struct seckey_info): Likewise.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-26 13:43:24 +09:00
NIIBE Yutaka a8618fdccd
agent: Initialize FP for the case of error return.
* agent/findkey.c (agent_write_private_key): Initialize FP.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-26 13:42:37 +09:00
NIIBE Yutaka 26939ea222
Use gpgrt_b64* API of libgpg-error.
* common/Makefile.am (common_sources): Remove b64enc.c and b64dec.c.
(module_maint_tests): Remove t-b64.
(t_b64_LDADD): Remove.
* common/util.h: Remove the internal API.
* common/ssh-utils.c (get_fingerprint): Use the gpgrt_b64 API.
(ssh_public_key_in_base64): Likewise.
* dirmngr/crlfetch.c (my_es_read, crl_close_reader): Likewise.
* dirmngr/dirmngr-client.c (data_cb, do_lookup): Likewise.
* dirmngr/misc.c (armor_data): Likewise.
* g10/export.c (export_one_ssh_key, export_secret_ssh_key): Likewise.
* tools/gpg-card.c (cmd_writecert): Likewise.
* tools/mime-parser.c (parse_message_cb, mime_parser_release)
(process_part_data): Likewise.
* tools/wks-util.c (wks_armor_key): Likewise.

--

GnuPG-bug-id: 6734
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-26 13:34:50 +09:00
Werner Koch 34f812475e
gpg: Fix last commit.
* g10/keyid.c (hash_public_key): Do not pass the version.
--

Fixes-commit: 1be7882344
2023-09-05 08:10:36 +02:00
Werner Koch 1be7882344
gpg: Add option --with-v5-fingerprint
* g10/gpg.c (oWithV5Fingerprint): New.
(opts): Add new option.
(main): Set option.
* g10/options.h (opt): Add with_v5_fingerprint.
* g10/keyid.c (hash_public_key): Factor out to ...
(do_hash_public_key): this.  Add new arg to foce v5 style hashing.
(v5_fingerprint_from_pk): New.
(v5hexfingerprint): New.
* g10/keylist.c (print_fingerprint): Print v5 fingerprint for v4 keys
if the option is set.
--

GnuPG-bug-id: 6705
2023-09-04 16:35:19 +02:00
NIIBE Yutaka d90f1e5fa4
agent: Fix timer round-up check when inserting an entry into cache.
* agent/cache.c (insert_to_timer_list): Round up when >= a half second.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-04 12:00:29 +09:00
NIIBE Yutaka 28364affa6
agent: Fix sock_inotify_fd handling.
* agent/gpg-agent.c (handle_connections): Also check SOCK_INOTIFY_FD
when spawning check_onw_socket_thread.  When removal of the socket
is detected, do same as AGENT_PROBLEM_SOCKET_TAKEOVER.

--

GnuPG-bug-id: 6692
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-04 10:34:42 +09:00
NIIBE Yutaka 5e47d5edd8
agent: Fix timer list management.
* agent/cache.c (insert_to_timer_list): Update TV_SEC of the top entry
when inserted.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-01 11:28:44 +09:00
NIIBE Yutaka 57125d3f5a
agent: Fix the previous commit.
* agent/cache.c (remove_from_timer_list_new): Fix cut&paste error.
TV_SEC field should not be touched.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-01 11:00:44 +09:00
NIIBE Yutaka 92de0387f0
agent: Introduce management of timer to expire cache entries.
* agent/cache.c (struct timer_s): New.
(struct cache_item_s): Add a member filed T for timer.
(the_timer_list, the_timer_list_new): New.
(insert_to_timer_list_new, insert_to_timer_list): New.
(remove_from_timer_list, remove_from_timer_list_new): New.
(housekeeping): Remove.
(compute_expiration, update_expiration): New.
(do_expire): New.
(TIMERTICK_INTERVAL): Remove.
(agent_cache_expiration): Use timer list to manage the expiration
of cache entries.
(agent_flush_cache): Call update_expiration when needed.
(agent_put_cache): Don't call housekeeping any more, but
update_expiration for an entry in question.
(agent_get_cache): Likewise.

--

GnuPG-bug-id: 6681
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-31 14:49:38 +09:00
NIIBE Yutaka 76a2f18028
agent: Better interaction between main loop and cache expiration.
* agent/agent.h (agent_cache_housekeeping): Remove.
(agent_cache_expiration): New.
* agent/cache.c (agent_cache_housekeeping): Remove.
(agent_cache_expiration): New.
* agent/gpg-agent.c (TIMERTICK_INTERVAL): Remove.
(handle_tick): Remove.
(handle_connections): Call agent_cache_expiration and use the timeout
value determined by the call.

--

GnuPG-bug-id: 6681
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-30 14:48:56 +09:00
NIIBE Yutaka 7025375e8b
agent: Have a thread monitoring parent PID and homedir.
* agent/gpg-agent.c (CHECK_PROBLEMS_INTERVAL): New.
(socket_takeover_detected): Remove.
(problem_detected): New.
(handle_tick): Don't check parent PID and homedir in this function.
(handle_connections): Spawn check_others_thread when needed.  Handle
AGENT_PROBLEM_PARENT_HAS_GONE and AGENT_PROBLEM_HOMEDIR_REMOVED.
(check_own_socket_thread): Check SHUTDOWN_PENDING variable in the
loop.  Use PROBLEM_DETECTED variable.
(check_others_thread): New.

--

GnuPG-bug-id: 6693
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-30 14:08:33 +09:00
NIIBE Yutaka 76896e2339
agent: Recover support CHECK_OWN_SOCKET_INTERVAL == 0.
* agent/gpg-agent.c (handle_connections): Only spawn the thread
when CHECK_OWN_SOCKET_INTERVAL > 0.
[CHECK_OWN_SOCKET_INTERVAL == 0] (check_own_socket_pid_cb)
(do_check_own_socket, check_own_socket_thread): Ifdef out.

--

GnuPG-bug-id: 6692
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-30 13:21:37 +09:00
NIIBE Yutaka b2826924ee
agent: Fix the handling of socket takeover.
* agent/gpg-agent.c (handle_connections): Check the takeover when
interrupted.
(check_own_socket_thread): Kick the loop when detected.

--

GnuPG-bug-id: 6692
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-30 11:26:07 +09:00
NIIBE Yutaka 95186ae92f
agent: Use a thread to monitor socket takeover.
* agent/gpg-agent.c (check_own_socket_running): Remove.
(socket_takeover_detected): New.
(check_own_socket): Remove.
(handle_tick): Don't call check_own_socket any more.
(handle_connections): Start off the check_own_socket_thread.
Check socket_takeover_detected to handle the event.
(do_check_own_socket): New, factoring out the task.
(check_own_socket_thread): Loop with the interval.

--

GnuPG-bug-id: 6692
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-30 10:57:36 +09:00
Werner Koch 9dd8fd4ae4
g13: Fix for new assuan_control.
* g13/g13.c (main): Fix assuan control code.
--

Fixes-commit: 1d73806972
GnuPG-bug-id: 6606
2023-08-29 13:23:48 +02:00
Werner Koch a430f22549
common: Prepare for more flags in start_new_service.
* common/asshelp.h (ASSHELP_FLAG_AUTOSTART): New.
* common/asshelp.c (start_new_service): Rename arg autostart to flags
and adjust checks.
(start_new_gpg_agent): Likewise.  Change all callers.
(start_new_keyboxd): Likewise.  Change all callers.
(start_new_dirmngr): Likewise.  Change all callers.
--

It is easier to have a generic flags arg instead of adding more and
more dedicated args.  verbose and debug are kept as they are because
they are not boolean.
2023-08-29 13:18:13 +02:00
NIIBE Yutaka 716e59b0b6
agent: Add agent_kick_the_loop function.
* agent/agent.h (agent_kick_the_loop): New.
* agent/gpg-agent.c [HAVE_W32_SYSTEM] (the_event2): New.
[HAVE_PSELECT_NO_EINTR] (event_pipe_fd): New.
[!HAVE_PSELECT_NO_EINTR] (main_thread_pid): New.
(create_an_event): New, factored out.
(get_agent_daemon_notify_event): Use create_an_event.
(handle_signal): Add a case for SIGCONT.
(agent_kick_the_loop): New.
(handle_connections): Call pselect possibly with the pipe.
Call eselect with THE_EVENT2.

--

GnuPG-bug-id: 6682
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-24 16:07:26 +09:00
NIIBE Yutaka 9e4d522239
tpm2d: Fix call to assuan_control.
* tpm2d/tpm2daemon.c (main): Use ASSUAN_CONTROL_REINIT_SYSCALL_CLAMP.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-16 09:05:53 +09:00
NIIBE Yutaka 1d73806972
gpg,agent,kbx,sm,scd,tpm2d,g13: Use assuan_control.
* agent/gpg-agent.c (thread_init_once): Call assuan_control.
* g10/gpg.c (main): Likewise.
* g13/g13.c (main): Likewise.
* kbx/keyboxd.c (thread_init_once): Likewise.
* scd/scdaemon.c (main): Likewise.
* sm/gpgsm.c (main): Likewise.
* tpm2d/tpm2daemon.c (main): Likewise.

--

GnuPG-bug-id: 6606
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-03 16:34:18 +09:00
NIIBE Yutaka ed4050e011
agent: Use new libassuan API for pipe server process.
* agent/call-daemon.c (struct wait_child_thread_parm_s): Remove PID
field.
(wait_child_thread): Don't touch the internals but call
assuan_pipe_wait_server_termination.
(daemon_start): Don't use PID.
(agent_daemon_dump_state): Don't use PID.
* agent/call-pinentry.c (watch_sock): Call assuan_pipe_kill_server.
(agent_popup_message_stop): Likewise.

--

GnuPG-bug-id: 6487
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-03 16:34:08 +09:00
NIIBE Yutaka 0821ceebfb
agent,dirmgr,gpg,g13,kbx,scd,sm,tmp2d: Remove ASSUAN_SYSTEM_NPTH.
* agent/gpg-agent.c (ASSUAN_SYSTEM_NPTH_IMPL): Remove.
(initialize_modules): Don't call assuan_set_system_hooks.
(main): Don't call assuan_sock_set_system_hooks.
* dirmngr/dirmngr.c (ASSUAN_SYSTEM_NPTH_IMPL): Remove.
(thread_init): Don't call assuan_set_system_hooks.
* g10/gpg.c (ASSUAN_SYSTEM_NPTH_IMPL): Remove.
(main): Don't call assuan_set_system_hooks.
* g13/g13.c (ASSUAN_SYSTEM_NPTH_IMPL): Remove.
(main): Set the syscall clamp with gpgrt_set_syscall_clamp.
Don't call assuan_set_system_hooks.
* kbx/keyboxd.c (ASSUAN_SYSTEM_NPTH_IMPL): Remove.
(initialize_modules): Don't call assuan_set_system_hooks.
(main): Don't call assuan_sock_set_system_hooks.
* scd/scdaemon.c (ASSUAN_SYSTEM_NPTH_IMPL): Remove.
(main): Don't call assuan_set_system_hooks.
* sm/gpgsm.c (ASSUAN_SYSTEM_NPTH_IMPL): Remove.
(main): Don't call assuan_set_system_hooks.
* tpm2d/tpm2daemon.c (ASSUAN_SYSTEM_NPTH_IMPL): Remove.
(main): Don't call assuan_set_system_hooks.

--

GnuPG-bug-id: 6606
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-03 16:34:00 +09:00
NIIBE Yutaka 5cad5f903e
agent,dirmngr,kbx,scdaemon: Use assuan_sock_accept.
* agent/gpg-agent.c (handle_connections): Use assuan_sock_accept.
* dirmngr/dirmngr.c (handle_connections): Ditto.
* kbx/keyboxd.c (handle_connections): Ditto.
* scd/scdaemon.c (handle_connections): Ditto.
* tpm2d/tpm2daemon.c (handle_connections): Ditto.

--

GnuPG-bug-id: 6599
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-03 16:33:51 +09:00
NIIBE Yutaka 0d20b79ab7
build: Require libassuan 3.0.0 or later.
* configure.ac (NEED_LIBASSUAN_API): Require the API version 3.0.
(NEED_LIBASSUAN_VERSION): Require 3.0.0 or later.

--

GnuPG-bug-id: 6606
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-03 16:33:43 +09:00
NIIBE Yutaka dad880155e
build: Update libassuan.m4 for API compatibility.
* m4/libassuan.m4: Update from libassuan master.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-26 11:29:05 +09:00
NIIBE Yutaka 1ddd69935d
gpg: Add parallelized filter for hashing.
* g10/options.h (COMPAT_PARALLELIZED): New.
* g10/filter.h (md_thd_filter_context_t): New type.
(md_thd_filter_set_md, md_thd_filter): New.
* g10/gpg.c (compatibility_flags): Update to support
COMPAT_PARALLELIZED.
* g10/mdfilter.c (struct md_thd_filter_context): New.
(lock_md, unlock_md, get_buffer_to_hash, put_buffer_to_recv): New.
(get_buffer_to_fill, put_buffer_to_send, md_thread): New.
(md_thd_filter, md_thd_filter_set_md): New.
* g10/sign.c (sign_file): Add support for md_thd_filter.
(sign_symencrypt_file): Likewise.

--

GnuPG-bug-id: 6570
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-25 12:10:07 +09:00
NIIBE Yutaka 95d9761509
sm: Use estream for I/O.
* sm/decrypt.c (gpgsm_decrypt): Use estream for the input.
* sm/encrypt.c (gpgsm_encrypt): Likewise.
* sm/gpgsm.c (open_read): Remove.
(main): Use open_es_fread for gpgsm_import_files.  Fix call of
gpgsm_encrypt, gpgsm_sign, gpgsm_verify and gpgsm_decrypt.
(open_es_fread): Use gnupg_check_special_filename and open_stream_nc.
* sm/gpgsm.h: Fix function declarations.
* sm/import.c (import_one): Use estream for the input.
(reimport_one, gpgsm_import, gpgsm_import_files): Likewise.
* sm/server.c (struct server_local_s): Rename MESSAGE_FD to
MESSAGE_FP.
(close_message_fp): Rename from close_message_fd.
(reset_notify): Follow the change of close_message_fp.
(cmd_encrypt, cmd_decrypt, cmd_verify, cmd_sign): Follow the change of
close_message_fp.  Use open_stream_nc to get estream.
(cmd_import): Likewise.
(cmd_export, cmd_delkeys, gpgsm_server): Follow the change of
close_message_fp.
(cmd_message): Setup MESSAGE_FP with open_stream_nc.
* sm/sign.c (hash_data): Use estream for the input.
(hash_and_copy_data): Likewise.
(gpgsm_sign): Likewise.
* sm/verify.c (hash_data): Use estream_t for FP.
(gpgsm_verify): Use estream_t for IN_FP and DATA_FP.

--

GnuPG-bug-id: 6592
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-25 10:04:18 +09:00
NIIBE Yutaka 30fc365124
dirmngr: Silence compiler when it's without LDAP.
* dirmngr/ks-action.c [!USE_LDAP] (ks_action_get): NEWER is not used.
* ks_action_query [!USE_LDAP] (ks_action_query): Ignore unused args.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-21 14:27:57 +09:00
NIIBE Yutaka eceba4f207
kbx: Fix error paths to fall back to D-lines.
* kbx/kbx-client-util.c (prepare_data_pipe): Return an error.
(kbx_client_data_new): Recover from an error by use of D-lines.
(kbx_client_data_release): Handle the case of use of D-lines.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-21 14:22:19 +09:00
Andre Heinecke 6e2412e74a
dirmngr: Add doc for faked-system-time
* dirmngr/dirmngr.c (gpgrt_opt_t): Use string for oFakedSystemTime.
(oFakedSystemTime): Use similar conversion as gpgsm has.
* dirmngr/dirmngr.texi (faked-system-time): Document it.

--
For testing X509 certificates this is usually required and
then confusing that the example from the gpgsm man page
does not work for dirmngr.
2023-07-19 11:27:08 +02:00
NIIBE Yutaka 6524becf28
Revert "kbx,w32: Disable the fd-passing."
This reverts commit 6944aefa3c.

--

The fd-passing works well on Windows with new libassuan (to be 3.0),
and it doesn't require ASSUAN_SOCKET_SERVER_FDPASSING actually.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-19 13:35:26 +09:00
NIIBE Yutaka ea1935252e
commond: Introduce FD2NUM to express conversion to number of fds.
* common/sysutils.h (FD2NUM): New.
* agent/call-pinentry.c (watch_sock): Use FD2NUM.
* agent/gpg-agent.c (handle_connections): Likewise.
* dirmngr/dirmngr.c (handle_connections): Likewise.
* dirmngr/http.c (connect_with_timeout): Likewise.
* kbx/keyboxd.c (handle_connections): Likewise.
* scd/scdaemon.c (handle_connections): Likewise.
* tpm2d/tpm2daemon.c (handle_connections): Likewise.

--

GnuPG-bug-id: 6598
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-18 14:43:36 +09:00
NIIBE Yutaka 521ec40aea
common,w32: Fix FD2INT macro.
* common/sysutils.h [HAVE_W32_SYSTEM] (FD2INT): Use intptr_t for
64-bit Windows.

--

GnuPG-bug-id: 6598
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-18 14:21:19 +09:00
NIIBE Yutaka ae188a3357
agent,build,w32: Fix use of SOCKET.
* configure.ac (HAVE_SOCKET): Detect SOCKET type.
* agent/command-ssh.c [HAVE_SOCKET] (start_command_handler_ssh): Use
SOCKET to cast.

--

GnuPG-bug-id: 6508
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-18 14:05:13 +09:00
NIIBE Yutaka 81055baf5c
dirmngr,kbk,tools: Fix type casting.
* dirmngr/http.c (send_request): Remove cast which is not needed.
* kbx/kbx-client-util.c (prepare_data_pipe): Cast to HANDLE.
* tools/gpg-connect-agent.c (do_open): Ditto.

--

GnuPG-bug-id: 6508
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-18 12:07:25 +09:00
NIIBE Yutaka b849c930e9
common: Introduce FD_DBG to display gnupg_fd_t value.
* common/sysutils.h (FD_DBG): New.
* agent/gpg-agent.c (check_nonce): Use FD_DBG.
(do_start_connection_thread, start_connection_thread_ssh): Likewise.
* common/iobuf.c (fd_cache_close, file_filter, do_open): Likewise.
(do_iobuf_fdopen): Likewise.
* dirmngr/dirmngr.c (check_nonce, start_connection_thread)
(handle_connections): Likewise.
* dirmngr/http.c (_my_socket_new, _my_socket_ref): Likewise.
(_my_socket_unref): Likewise.
* g10/decrypt.c (decrypt_message_fd): Likewise.
* g10/encrypt.c (encrypt_crypt): Likewise.
* g10/openfile.c (open_outfile): Likewise.
* g10/plaintext.c (get_output_file, hash_datafile_by_fd): Likewise.
* g10/verify.c (gpg_verify): Likewise.
* kbx/keyboxd.c (check_nonce, do_start_connection_thread): Likewise.
* scd/scdaemon.c (start_connection_thread): Likewise.
(handle_connections): Likewise.
* sm/gpgsm.c (open_es_fread, open_es_fwrite): Likewise.
* tpm2d/tpm2daemon.c (start_connection_thread): Likewise.
(handle_connections): Likewise.

--

GnuPG-bug-id: 6597
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-18 11:54:16 +09:00
NIIBE Yutaka ee9e3578ce
gpg: Use gnupg_fd_t for iobuf_get_fd and is_secured_file.
* common/iobuf.c (iobuf_get_fd): Return type is now gnupg_fd_t.
* common/iobuf.h (iobuf_get_fd): Fix the return type.
* g10/misc.c (is_secured_file): Argument is now gnupg_fd_t.
* g10/main.h (is_secured_file): Fix the argument type.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-14 15:52:08 +09:00
NIIBE Yutaka 5d375bb168
gpg: Use is_secured_filename before opening the file.
* g10/gpg.c (print_mds): Check by is_secured_filename, earlier.
* g10/tdbdump.c (import_ownertrust): Likewise.

--

GnuPG-bug-id: 6508
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-14 15:49:23 +09:00
NIIBE Yutaka cf270b0d30
sm: Fix open_es_fread and open_es_fwrite for gnupg_fd_t.
* sm/gpgsm.c (open_es_fread, open_es_fwrite): Use gnupg_fd_t
and open_stream_nc.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-13 14:37:20 +09:00
NIIBE Yutaka ea625c74f0
sm: Use open_stream_nc for do_listkeys.
* sm/server.c (do_listkeys): Use open_stream_nc.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-13 13:53:49 +09:00
NIIBE Yutaka 69c1d81284
sm: Use gnupg_fd_t and open_stream_nc for assuan_get_input_fd.
* sm/server.c (cmd_genkey): Use open_stream_nc for input and output.
(cmd_getauditlog): Use open_stream_nc for output.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-13 13:46:43 +09:00
NIIBE Yutaka fb046ccd93
sm: Use open_stream_nc for HANDLE by assuan_get_output_fd.
* sm/server.c (cmd_encrypt): Use gnupg_fd_t for OUT_FD.
Call open_stream_nc with OUT_FD.
(cmd_decrypt, cmd_verify, cmd_sign, cmd_export): Likewise.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-13 11:18:47 +09:00
NIIBE Yutaka 23bcb78d27
gpg: Add support for Subkey-Expire-Date.
* g10/keygen.c (enum para_name): Add pSUBKEYEXPIREDATE.
(proc_parameter_file): Add support for pSUBKEYEXPIREDATE.
(read_parameter_file): Add "Subkey-Expire-Date".

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-12 14:04:28 +09:00
NIIBE Yutaka b07b5144ff
gpg: Fix expiration time when Creation-Date is specified.
* g10/keygen.c (parse_expire_string_with_ct): New function, optionally
supply the creation time.
(parse_expire_string): Use parse_expire_string_with_ct with no
creation time.
(proc_parameter_file): Use parse_expire_string_with_ct possibly with
the creation time.

--

GnuPG-bug-id: 5252
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-12 13:34:19 +09:00
NIIBE Yutaka 067bc2ed4c
gpg: Move the check by is_secured_file earlier.
* g10/decrypt.c (decrypt_message_fd): Call is_secured_file here.
* g10/plaintext.c (get_output_file): Remove the call.

--

Fixes-commit: 71625f56fd
GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-11 13:49:41 +09:00
NIIBE Yutaka 16d135c396
common: Change iobuf_fdopen argument type to gnupg_fd_t.
* common/iobuf.h (iobuf_fdopen): Use gnupg_fd_t.
* common/iobuf.c (iobuf_fdopen): Use gnupg_fd_t.
(iobuf_sockopen): Call do_iobuf_fdopen.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-11 11:21:05 +09:00
NIIBE Yutaka 250733c0d8
common: Add gnupg_check_special_filename.
* common/sysutils.h (gnupg_check_special_filename): New.
* common/sysutils.c (gnupg_check_special_filename): New.
* common/iobuf.c (translate_file_handle): Remove.
(iobuf_is_pipe_filename): Use gnupg_check_special_filename.
(do_open): Use gnupg_check_special_filename.
* g10/plaintext.c (get_output_file): Use gnupg_check_special_filename
and open_stream_nc.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-11 10:46:36 +09:00
NIIBE Yutaka 37343db08f
common,gpg,kbx: Factor out open_stream_nc.
* common/sysutils.h (open_stream_nc): New.
* common/sysutils.c (open_stream_nc): New.
* g10/decrypt.c (decrypt_message_fd): Use open_stream_nc.
* g10/server.c (cmd_verify): Likewise.
* kbx/kbxserver.c (prepare_outstream): Likewise.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-10 11:22:43 +09:00
NIIBE Yutaka 5bc949d230
common:w32: Fix gnupg_w32_set_errno.
* common/sysutils.c (gnupg_w32_set_errno): Return EC.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-10 11:20:13 +09:00
Werner Koch 9f39e4da29
gpg: Add algo constants for PQC.
* common/openpgpdefs.h (PUBKEY_ALGO_KY768_25519): New.
(PUBKEY_ALGO_KY1024_448): New.
(PUBKEY_ALGO_DIL3_25519): New.
(PUBKEY_ALGO_DIL5_448): New.
(PUBKEY_ALGO_SPHINX_SHA2): New.
* g10/keygen.c (parse_key_parameter_part): Force v5 keys for these
  algos.
* g10/keyid.c (pubkey_string): Add mapping.
* g10/misc.c (openpgp_pk_algo_usage): Add standard key usage.
--

See draft-wussler-openpgp-pqc-01.txt for the code points.  To limit
the number of algorithms, only MUST and SHOULD algorithms are
considered.
2023-07-07 10:21:39 +02:00
NIIBE Yutaka 8cacfce898
kbx: Fix memory leak at spawning a thread for data pipe.
* kbx/kbx-client-util.c (prepare_data_pipe): Release
the attribute for thread creation.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-06 16:02:14 +09:00
NIIBE Yutaka 2abea42d9c
kbx: Use es_sysopen_nc instead of es_fdopen_nc.
* kbx/kbxserver.c (prepare_outstream): Use es_sysopen_nc
and avoid the use of translate_sys2libc_fd.

--

On Windows, it's better directly use the system HANDLE.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-06 10:25:15 +09:00
NIIBE Yutaka f2dcd158a5
gpg: Fix gpg --server mode on Windows.
* g10/server.c (cmd_encrypt): Don't translate_sys2libc_fd, since it
requires HANDLE on Windows.
(cmd_decrypt): Likewise.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-05 13:22:16 +09:00
NIIBE Yutaka 577baf4af3
gpg: Format the value of type gnupg_fd_t by casting to int.
* g10/openfile.c (open_outfile): Cast to int.
* g10/encrypt.c (encrypt_crypt): Ditto.
* g10/decrypt.c (decrypt_message_fd): Ditto.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-05 13:11:16 +09:00
NIIBE Yutaka 3fb69641e8
gpg: Use gnupg_fd_t for decryption and sign.
* g10/decrypt.c (decrypt_message_fd): Use gnupg_fd_t.
* g10/plaintext.c (hash_datafile_by_fd): Use  gnupg_fd_t.
* g10/main.h: Fix the declarations.
* g10/mainproc.c (struct mainproc_context): Use gnupg_fd_t for
DATA_FD.
(proc_compressed_cb, proc_signature_packets): Follow the change.
(proc_signature_packets_by_fd): Use gnupg_fd_t.
* g10/packet.h: Fix the declaration.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-05 10:29:23 +09:00
NIIBE Yutaka 2c2516f03a
gpg: Use gnupg_fd_t for encrypt_crypt and gpg_verify.
* common/iobuf.h (iobuf_fdopen_nc): Use gnupg_t.
* common/iobuf.c (iobuf_fdopen_nc): Use gnupg_t.
* g10/main.h (encrypt_crypt, gpg_verify): Use gnupg_fd_t.
* g10/encrypt.c (encrypt_crypt): Use gnupg_fd_t.
(encrypt_crypt_files): Follow the change.
* g10/gpg.c (main): Follow the change.
* g10/verify.c (gpg_verify): Use gnupg_fd_t.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-05 10:05:31 +09:00
NIIBE Yutaka 68d3a73ea7
gpg: Use gnupg_fd_t for open_outfile.
* g10/main.h (open_outfile): Use gnupg_fd_t instead of int.
* g10/openfile.c (open_outfile): Likewise.  Use GNUPG_INVALID_FD.
* g10/dearmor.c (dearmor_file, enarmor_file): Follow the change.
* g10/encrypt.c (encrypt_simple): Likewise.
* g10/export.c (do_export): Likewise.
* g10/revoke.c (gen_desig_revoke, create_revocation): Likewise.
* g10/sign.c (sign_file, clearsign_file, sign_symencrypt_file):
Likewise.

--

GnuPG-bug-id: 6580
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-05 09:36:00 +09:00
NIIBE Yutaka dc13361524
dirmngr: Enable the call of ks_ldap_help_variables when USE_LDAP.
* dirmngr/server.c [USE_LDAP] (cmd_ad_query): Conditionalize.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-05 09:29:54 +09:00
NIIBE Yutaka 2c5a93e66e
gpg:card: Remove the code for GnuPG version 1.
* g10/card-util.c [GNUPG_MAJOR_VERSION == 1] (get_data_from_file):
Remove the old code.
(put_data_to_file): Likewise.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-05 09:26:16 +09:00
Werner Koch 334f5d95c8
Merge branch 'STABLE-BRANCH-2-4' into master 2023-07-04 17:37:54 +02:00
NIIBE Yutaka b5efb52d43
agent: Fix formatting thread ID of nPth.
* agent/call-pinentry.c (agent_query_dump_state): Use %lx to
format thread ID.

--

Fixes-commit: ba6f8b3d9e
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-03 10:46:46 +09:00
NIIBE Yutaka a0ff2919f7
tools:gpg-connect-agent: Fix use of HANDLE on Windows.
* tools/gpg-connect-agent.c [HAVE_W32_SYSTEM] (do_open): Use %p to
format the HANDLE.
[HAVE_W32_SYSTEM] (do_close): Use gnupg_parse_fdstr to parse the
string representation of the HANDLE.  Use %p.

--

GnuPG-bug-id: 6508
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-03 10:20:06 +09:00
NIIBE Yutaka 250fff0f6e
common:iobuf: Avoid losing bits of HANDLE on Windows 64-bit.
* common/iobuf.c (translate_file_handle): Change the return type to
gnupg_fd_t, not to lose the bits for HANDLE silently.
(do_iobuf_fdopen): Use the type gnupg_fd_t for the first argument.
(do_open): Use do_iobuf_fdopen instead of iobuf_fdopen.
(iobuf_fdopen, iobuf_fdopen_nc): Follow the change of API.

--

GnuPG-bug-id: 6508
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-30 15:56:43 +09:00
NIIBE Yutaka 6049d61991
common: Fix the cast for 64-bit Windows.
* common/sysutils.c (translate_sys2libc_fd_int): Fix the cast.

--

FD should have a valid value here.  For erroneous cases, it must be
rejected by argparse handling.

GnuPG-bug-id: 6551
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-29 14:04:32 +09:00
NIIBE Yutaka 3672c29156
common: Raise an error correctly in check_special_filename.
* common/sysutils.c (check_special_filename): Use gnupg_parse_fdstr
to check an error.

--

GnuPG-bug-id: 6551
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-29 14:01:40 +09:00
NIIBE Yutaka cacb018992
tools:gpgtar: Clean up the use of --status-fd.
* common/sysutils.c (gnupg_parse_fdstr): Rename from
gnupg_sys2libc_fdstr, as there is no translation any more.
* common/sysutils.h (gnupg_parse_fdstr): Rename from
gnupg_sys2libc_fdstr.
* tools/gpgtar.c (main): Use gnupg_parse_fdstr, in cleaner way.

--

GnuPG-bug-id: 6562
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-28 13:59:52 +09:00
NIIBE Yutaka 7cfbf0dd72
scd:piv: Fix authentication with Administration Key.
* scd/app-piv.c (auth_adm_key): Fix the value of the Response Tag.
(do_setattr): Fix the comment.

--

Reported-by: Heiko Schäfer <heiko@schaefer.name>
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-27 15:43:35 +09:00
NIIBE Yutaka 631c23b664
gpgtar: Use FD on POSIX.
* tools/gpgtar.c (main): Fix the use of the union.

--

Fixes-commit: 2756147e39
GnuPG-bug-id: 6562
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-27 14:58:13 +09:00
NIIBE Yutaka b9b0c18320
common,gpg,sm,tools: Don't remove translate_sys2libc_fd_int.
* common/sysutils.c (translate_sys2libc_fd_int): Recover.
(translate_sys2libc_fdstr): Remove.
(check_special_filename): Follow the change.
* common/sysutils.h (translate_sys2libc_fd_int): Recover.
(translate_sys2libc_fdstr): Remove.
* g10/gpg.c, g10/gpgv.c, sm/gpgsm.c: Revert the changes.
* tools/gpg-auth.c, tools/gpg-card.c, tools/gpg-pair-tool.c: Likewise.
* tools/gpg-wks-client.c, tools/gpgconf.c: Likewise.

--

GnuPG-bug-id: 6551
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-27 14:44:01 +09:00
NIIBE Yutaka 72ac77c4fa
agent: Fix cast mistake for Windows.
* agent/call-daemon.c [HAVE_W32_SYSTEM] (daemon_start): Use %p
for the format with a pointer.

--

GnuPG-bug-id: 6508
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-26 14:58:58 +09:00
NIIBE Yutaka 76df934929
tests:gpgscm: Add annotation for unreachable code for GCC.
* tests/gpgscm/scheme.c [__GNUC__] (type_to_string): Use
__builtin_unreachable for GCC.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-26 14:47:28 +09:00
NIIBE Yutaka 1f9a4fbc7e
gpg,w32: Add comment about debug output of ShellExecuteEx.
* g10/photoid.c (w32_system): Add comment about hInstApp, why we use
the integer value of possibly smaller size for the debug output.

--

GnuPG-bug-id: 6508
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-26 10:59:35 +09:00
NIIBE Yutaka f0ecc07c4e
tools: Fix use of EXCEPTS when spawning a process.
* tools/gpgtar-create.c (gpgtar_create) [HAVE_W32_SYSTEM]: Use HANDLE.
* tools/gpgtar-extract.c (gpgtar_extract) [HAVE_W32_SYSTEM]: Likewise.
* tools/gpgtar-list.c (gpgtar_list) [HAVE_W32_SYSTEM]: Likewise.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-26 10:17:23 +09:00
NIIBE Yutaka 87a73e8eb0
common: Remove translate_sys2libc_fd_int.
* common/sysutils.c (translate_sys2libc_fd_int): Remove.
(check_special_filename): Use translate_sys2libc_fdstr.
* common/sysutils.h (translate_sys2libc_fd_int): Remove.

--

GnuPG-bug-id: 6551
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-23 13:37:08 +09:00
NIIBE Yutaka 2756147e39
gpg,sm,tools: Use string for option --*-fd.
* g10/gpg.c (opts): Use string for oLoggerFD, oOverrideSessionKeyFD,
oStatusFD, oAttributeFD, oCommandFD, and oPassphraseFD.
(main): Use translate_sys2libc_fdstr.
* g10/gpgv.c (opts): Use string for oLoggerFD, and oStatusFD.
(main): Use translate_sys2libc_fdstr.
* sm/gpgsm.c (opts): Use string for oLoggerFD, oStatusFD, and
oPassphraseFD.
(main): Use translate_sys2libc_fdstr.
* tools/gpg-auth.c (opts): Use string for oStatusFD.
(main): Use translate_sys2libc_fdstr.
tools/gpg-card.c (opts): Use string for oStatusFD.
(main): Use translate_sys2libc_fdstr.
* tools/gpg-pair-tool.c (opts): Use string for oStatusFD.
(main): Use translate_sys2libc_fdstr.
* tools/gpg-wks-client.c (opts): Use string for oStatusFD.
(main): Use translate_sys2libc_fdstr.
* tools/gpgconf.c (opts): Use string for oStatusFD.
(main): Use translate_sys2libc_fdstr.
* tools/gpgtar-create.c (gpgtar_create): Fix for opt.status_fd.
* tools/gpgtar-extract.c (gpgtar_extract): Fix for opt.status_fd.
* tools/gpgtar-list.c (gpgtar_list): Fix for opt.status_fd.
* tools/gpgtar.c (opts): Use string for oStatusFD.
(main): Use translate_sys2libc_fdstr.
* tools/gpgtar.h (opts): Use string for oStatusFD.

--

GnuPG-bug-id: 6551
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-23 13:22:00 +09:00
NIIBE Yutaka 04d0851cca
common: Add gnupg_sys2libc_fdstr function.
* common/sysutils.c (gnupg_sys2libc_fdstr): New.
(translate_sys2libc_fdstr): Use gnupg_sys2libc_fdstr.

--

GnuPG-bug-id: 6551
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-23 13:05:29 +09:00
NIIBE Yutaka e9e7b5425f
common: Add translate_sys2libc_fdstr.
* common/sysutils.c (translate_sys2libc_fdstr): New.

--

GnuPG-bug-id: 6551
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-22 11:38:44 +09:00
zhangguangzhi 28a4d0d4f5
kbx: Close file handle when return.
* kbx/keybox-dump.c (_keybox_dump_find_dups): Close FP on the error
paths.

--

GnuPG-bug-id: 6495
Signed-off-by: zhangguangzhi <zhangguangzhi3@huawei.com>
2023-06-20 09:18:37 +09:00
zhangguangzhi be77c05532
delete redundant characters
--

GnuPG-bug-id: 6482
Signed-off-by: zhangguangzhi <zhangguangzhi3@huawei.com>
2023-06-20 09:08:29 +09:00
Werner Koch e16fc3e19c
w32: Map ERROR_FILE_INVALID to EIO.
* common/sysutils.c (map_w32_to_errno): Add mapping.
--

We see this error sometimes when writing to an USB connected disk.
2023-06-09 13:46:56 +02:00
Andre Heinecke 3c57aee263
speedo,w32: Call gpgconf --kill all
* build-aux/speedo/w32/inst.nsi: Use kill all instead of
explicitly killing processes.
2023-06-09 12:42:25 +02:00
NIIBE Yutaka 5170c366ee
common: Update t-exechelp to write/read smaller chunks.
* common/t-exechelp.c (run_server): Use syshd.  Write with 4K buffer.
(test_pipe_stream): Read with 4K buffer.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-09 11:25:17 +09:00
NIIBE Yutaka 1b0ce9918c
tests: Fix call-with-io deadlock.
* tests/gpgscm/ffi.c (es_wrap): Ifdef-out.
[HAVE_W32_SYSTEM] (read_from_pipe): New.
(do_process_spawn_io): Rename from do_process_spawn.  Do I/O
with no deadlock.
* tests/gpgscm/tests.scm (call-with-io): Use process-spawn-io.
(es-read-all): Remove.

--

GnuPG-bug-id: 6523
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-08 14:39:50 +09:00
NIIBE Yutaka f5656ff363
kbx: Fix datastream_thread and use the data pipe.
* g10/call-keyboxd.c (gpg_keyboxd_deinit_session_data): Release
the assuan connection before kbx_client_data_release.
(open_context): Enable use of the data pipe.
* sm/keydb.c (gpgsm_keydb_deinit_session_data): Release the
assuan connection before kbx_client_data_release.
(open_context): Enable use of the data pipe.
* kbx/kbx-client-util.c (struct kbx_client_data_s): Add THD field.
(prepare_data_pipe): Close the pipe output end as it's been sent
already.  Remember the KCD->THD, so that it can be joined later.
(datastream_thread): Finish when reading no data from the pipe.
(kbx_client_data_release): Join the thread.  Then, we can safely
call es_fclose on the FP.

--

GnuPG-bug-id: 6512
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-07 15:26:34 +09:00
NIIBE Yutaka 9433dfa5dd
common: Add test case for IPC with spawned process.
* common/Makefile.am (module_tests): Add t-exechelp.
* common/t-exechelp.c [HAVE_W32_SYSTEM] (print_open_fds)
(test_close_all_fds, main): Exclude the test_close_all_fds test.
(run_server, test_pipe_stream): New.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-07 09:08:58 +09:00
Werner Koch 22350d0768
doc: Replace remaining "gpg2" by "gpg".
--
2023-06-01 12:43:51 +02:00
NIIBE Yutaka ef4f22b9d9
gpg: Graceful exit for signature checking with --batch.
* g10/mainproc.c (check_sig_and_print): Don't abort computation in
the function, but returns an error.
(proc_tree): Break the loop, when check_sig_and_print returns an
error.

--

GnuPG-bug-id: 6512
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-01 11:58:53 +09:00
NIIBE Yutaka 0fba0bbc62
w32: Fix use of assuan_sendfd.
* kbx/kbx-client-util.c (prepare_data_pipe): Use _get_osfhandle
for pipe to be used for sentfd.
[HAVE_W32_SYSTEM] (datastream_thread): Add the case of NREAD==0.
* tools/gpg-connect-agent.c (do_sendfd): Use es_syshd instead
of es_fileno.
[HAVE_W32_SYSTEM] (do_open): Use %p for formating HANDLE.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-01 09:10:14 +09:00
Werner Koch 6ed61d98a0
Add release dates of 2.4 versions to NEWS
--
2023-05-31 09:38:17 +02:00
Werner Koch 2783b786a9
agent: Do not overwrite a key file by a shadow key file.
* agent/findkey.c (agent_write_private_key): Partly rewrite to align
with 2.2 code and to make sure that we don't overwrite a real key.
(is_shadowed_key): New.
--

This change is now also needed in 2.4 due to the the former change
"Create and use Token entries to track the display s/n".

GnuPG-bug-id: 6386
2023-05-26 14:27:19 +02:00
Werner Koch a216e9c028
agent: Update key files by first writing to a temp file.
* agent/findkey.c (fname_from_keygrip): New.
(agent_write_private_key): Use here.  Use temp file for updating.
(agent_update_private_key): Use fname_from_keygrip and use gnupg
rename function instead of a vanilla rename.
2023-05-26 14:27:17 +02:00
Werner Koch 1d23dc9389
agent: Create and use Token entries to track the display s/n.
* agent/findkey.c (agent_write_private_key): Add arg dispserialno and
update the token.
(agent_write_shadow_key): Add arg dispserialno and adjust all callers.
--

GnuPG-bug-id: 6135

Note that this has been forward ported from 2.2
2023-05-26 14:27:16 +02:00
Werner Koch ec0c35d1b8
common: New function nve_set
* common/name-value.c (nve_set): New.
--

Taken from 2.2 commit 706adf6691
2023-05-26 14:27:15 +02:00
NIIBE Yutaka f15a643a2d
agent,dirmngr: Shutdown fix for supervised mode.
* agent/gpg-agent.c (handle_connections): Break if supervised.
* dirmngr/dirmngr.c (is_supervised): New.
(handle_connections): Break if supervised.

--

For supervised agent/dirmngr, 'systemctl stop' behaves just like
'gpgconf --kill', ignoring existing connections.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-26 15:28:13 +09:00
Werner Koch 09a96c9e1b
gpg: Skip keys found via ADSKs.
* g10/encrypt.c (write_pubkey_enc): Indicate encryption to an ADSK.
* g10/getkey.c (finish_lookup): Skip ADKS keys.
--

If a key is searched by fingerprint or keyid and it happens that this
is an ADSK (subkey with the RENC usage), we need to skip this key
because it is not the key we actually want to encrypt to.  The actual
ADSK key is taken later by looking at all subkeys of the actual
selected key.

This is related to
GnuPG-bug-id: 6504
2023-05-25 16:50:00 +02:00
Werner Koch e9dd47d789
gpg: Fix searching for the ADSK key when adding an ADSK.
* g10/keyedit.c (menu_addadsk): Request an exact search.
* g10/getkey.c (finish_lookup): Add an debug output.
--

GnuPG-bug-id: 6504
2023-05-25 12:01:07 +02:00
NIIBE Yutaka 39a4373780
po: Update Japanese Translation.
--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-25 13:43:50 +09:00
NIIBE Yutaka 6984ddc6eb
common,w32: Fix gnupg_process_release.
* common/exechelp-w32.c: Close the handle of the process.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-25 13:43:41 +09:00
Werner Koch 000b82ade7
gpg: Return ERROR status for --quick-sign-key.
* g10/keyedit.c (keyedit_quick_sign): Return an error status line.
--
2023-05-24 16:05:41 +02:00
Werner Koch 8295fb3f0b
w32: Add missing supportedOS Ids for Windows-10
--
2023-05-24 14:17:06 +02:00
Werner Koch 3a438a1cc3
w32: Add missing manifests and set a requestedExecutionLevel.
* agent/gpg-agent.w32-manifest.in: New.
* dirmngr/dirmngr-client-w32info.rc: New.
* dirmngr/dirmngr-client.w32-manifest.in: New.
* dirmngr/dirmngr-w32info.rc: New.
* dirmngr/dirmngr.w32-manifest.in: New.
* dirmngr/dirmngr_ldap-w32info.rc: New.
* dirmngr/dirmngr_ldap.w32-manifest.in: New.
* g10/gpgv-w32info.rc: New.
* g10/gpgv.w32-manifest.in: New.
* kbx/keyboxd.w32-manifest.in: New.
* scd/scdaemon.w32-manifest.in: New.
* sm/gpgsm.w32-manifest.in: New.
--

This avoids the use of the VirtualStore uner Windows.

GnuPG-bug-id: 6503
2023-05-24 12:14:06 +02:00
Werner Koch 42bea7de16
common,w32: Set a proper error code when creating an output file.
* common/iobuf.c (direct_open) [W32]: Set errno.
(fd_cache_open): Ditto.
--
2023-05-24 12:13:56 +02:00
Werner Koch 7e681da1b2
sm: Emit STATUS_FAILURE for non-implemented commands.
* sm/gpgsm.c (main): Do it here.
2023-05-24 12:13:53 +02:00
Werner Koch 097701e698
gpgtar: Emit FAILURE status line.
* tools/gpgtar.c (main): Write status line before exit.
--

Due to the new way we support gpgtar in GPGME we need status lines to
detect a final error.

GnuPG-bug-id: 6497
2023-05-24 12:13:48 +02:00
Werner Koch faf0a97b2e
gpg: Improve error code for file already exists.
* g10/plaintext.c (get_output_file): Fix error code.
2023-05-24 12:12:34 +02:00
NIIBE Yutaka 2f872fa68c
gpg: Report BEGIN_* status before examining the input.
* common/miscellaneous.c (is_openpgp_compressed_packet)
(is_file_compressed): Moved to ...
* common/iobuf.c: ... in this file.
(is_file_compressed): Change the argument to INP, the iobuf.
* common/util.h (is_file_compressed): Remove.
* common/iobuf.h (is_file_compressed): Add.
* g10/cipher-aead.c (write_header): Don't call write_status_printf
here.
(cipher_filter_aead): Call write_status_printf when called with
IOBUFCTRL_INIT.
* g10/cipher-cfb.c (write_header): Don't call write_status_printf
here.
(cipher_filter_cfb): Call write_status_printf when called with
IOBUFCTRL_INIT.
* g10/encrypt.c (encrypt_simple): Use new is_file_compressed function,
after call of iobuf_push_filter.
(encrypt_crypt): Likewise.
* g10/sign.c (sign_file): Likewise.

--

GnuPG-bug-id: 6481
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-24 10:36:04 +09:00
NIIBE Yutaka b789ada2b0
scd: Fix send_client_notifications for Windows.
* scd/command.c (send_client_notifications): Don't use assuan_get_pid
for Windows.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-17 15:28:01 +09:00
NIIBE Yutaka d221062769
w32: Also use _putenv_s for gnupg_unsetenv.
* common/sysutils.c (gnupg_setenv): Only enable use of _putenv_s with
Security Feature in the CRT.
(gnupg_unsetenv): Use _putenv_s when available.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-16 19:11:16 +09:00
NIIBE Yutaka 86cdb49097
w32: Use _putenv_s.
* common/sysutils.c (gnupg_setenv): Use _putenv_s.

--

This may break build on original MinGW, but works well with MinGW-W64.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-16 16:25:13 +09:00
NIIBE Yutaka 5c7c6065f3
w32: Remove support of Windows 95/98/Me.
* g10/photoid.c (VER_PLATFORM_WIN32_WINDOWS): Remove fallback
definition.
(get_default_photo_command): Remove use of "start /w" for Windows 95.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-16 10:19:02 +09:00
Werner Koch 23bb92b755
common: Fix malloc nit in regression test.
* common/t-iobuf.c: Add boilerplate.
(xmalloc): New.  Use it everywhere.
--

GnuPG-bug-id: 6483
2023-05-11 15:52:05 +02:00
NIIBE Yutaka a035938216
common,agent,gpg,dirmngr,g13,scd,tests,tools: New spawn function.
* common/exechelp-posix.c (do_exec, gnupg_spawn_process): Remove.
(check_syscall_func, pre_syscall, post_syscall) : New.
(do_create_socketpair, posix_open_null, call_spawn_cb): New.
(my_exec, spawn_detached, gnupg_spawn_helper): New.
(gnupg_process_spawn, process_kill, gnupg_process_terminate): New.
(gnupg_process_get_fds, gnupg_process_get_streams): New.
(process_vctl, gnupg_process_ctl): New.
(gnupg_process_wait, gnupg_process_release): New.
(gnupg_process_wait_list): New.
* common/exechelp-w32.c: Add definition of _WIN32_WINNT as 0x600.
(check_syscall_func, pre_syscall, post_syscall): New.
(gnupg_spawn_process): Remove.
(check_windows_version): New.
(spawn_detached, gnupg_spawn_helper, gnupg_process_spawn): New.
(gnupg_process_get_fds, gnupg_process_get_streams): New.
(process_kill, process_vctl, gnupg_process_ctl): New.
(gnupg_process_wait, gnupg_process_terminate): New.
(gnupg_process_release, gnupg_process_wait_list): New.
* common/exechelp.h: Re-write for new API.
* common/exectool.c (gnupg_exec_tool_stream): Follow the change.
* common/asshelp.c (start_new_service): Likewise.
* agent/genkey.c (do_check_passphrase_pattern): Likewise.
* dirmngr/ldap-wrapper.c (struct wrapper_context_s): Use PROC.
(destroy_wrapper): Follow the change of API.
(read_log_data): Follow the change of API, use printable_pid.
(ldap_reaper_thread, ldap_wrapper_release_context): Likewise.
(ldap_wrapper_connection_cleanup, ldap_wrapper): Likewise.
* g10/photoid.c (run_with_pipe): Follow the change of API.
(show_photo): Likewise.
* g13/be-encfs.c (run_umount_helper): Likewise.
(run_encfs_tool): Likewise.
* g13/g13.c: Add including ./common/exechelp.h.
* g13/mount.c: Likewise.
* g13/runner.c: Follow the change of API.
* g13/runner.h: Follow the change of API.
* scd/app.c (setup_env): New.
(report_change): Follow the change of API.
* tests/gpgscm/ffi.c (proc_object_finalize): New.
(proc_object_to_string): New.
(proc_wrap, proc_unwrap): New.
(do_spawn_process): Remove.
(do_process_spawn): New.
(setup_std_fds): New.
(do_spawn_process_fd): Remove.
(do_process_spawn_fd): New.
(do_wait_process): Remove.
(do_process_wait): New.
(do_wait_processes): Remove.
* tests/gpgscm/t-child.scm: Follow the change of API.
* tests/gpgscm/tests.scm: Likewise.
* tests/openpgp/defs.scm: Likewise.
* tests/tpm2dtests/defs.scm: Likewise.
* tools/gpg-card.c: Likewise.
* tools/gpgconf-comp.c: Likewise.
* tools/gpgconf.c: Likewise.
* tools/gpgtar-create.c: Likewise.
* tools/gpgtar-extract.c: Likewise.
* tools/gpgtar-list.c: Likewise.

--

GnuPG-bug-id: 6275
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-11 19:18:21 +09:00
Werner Koch 1e41878bf2
Prepare new development cycle
--
2023-05-10 10:23:59 +02:00
264 changed files with 11925 additions and 6307 deletions

View File

@ -1,2 +1,6 @@
# indent: Modernize mem2str.
6a80d6f9206eae2c867c45daa5cd3e7d6c6ad114
# doc: Fix spelling errors found by lintian.
2ed1f68b48db7b5503045386de0500fddf70077e
# indent: Re-indent a function
869d1df270c0ccc3a9f792167b96d678a932b37e

View File

@ -220,6 +220,9 @@ Jussi Kivilinna <jussi.kivilinna@iki.fi>
Kyle Butt <kylebutt@gmail.com>
2013-05-29:CAAODAYLbCtqOG6msLLL0UTdASKWT6u2ptxsgUQ1JpusBESBoNQ@mail.gmail.com:
Mario Haustein <mario.haustein@hrz.tu-chemnitz.de>
2022-09-26:8149069.T7Z3S40VBb@localdomain:
Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
2018-07-13:c397e637-f1ce-34f0-7e6a-df04a76e1c35@ssi-schaefer.com:

View File

@ -24,7 +24,7 @@ WITH_MSI=1
# Location of the released tarball archives. This is prefixed by
# the variable RELEASE_ARCHIVE in ~/.gnupg-autogen.rc. For example:
# RELEASE_ARCHIVE=user@host:archive/tarballs
RELEASE_ARCHIVE_SUFFIX = gnupg/v2.4
RELEASE_ARCHIVE_SUFFIX = gnupg/v2.5
# The variable RELEASE_SIGNKEY in ~/.gnupg-autogen.rc is used
# to specify the key for signing. For example:
# RELEASE_SIGNKEY=D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
@ -247,8 +247,8 @@ release:
mkopt=""; \
if [ -n "$$CUSTOM_SWDB" ]; then \
mkopt="CUSTOM_SWB=1"; \
x=$$(grep '^OVERRIDE_TARBALLS=' \
$$HOME/.gnupg-autogen.rc|cut -d= -f2);\
x=$$(grep '^[[:blank:]]*OVERRIDE_TARBALLS[[:blank:]]*=' \
$$HOME/.gnupg-autogen.rc|cut -d= -f2|xargs);\
if [ -f "$$x/swdb.lst" ]; then \
echo "/* Copying swdb.lst from the overrides directory */"; \
cp "$$x/swdb.lst" . ; \
@ -275,13 +275,15 @@ release:
sign-release:
+(set -e; \
test $$(pwd | sed 's,.*/,,') = dist || cd dist; \
x=$$(grep '^RELEASE_ARCHIVE=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
x=$$(grep '^[[:blank:]]*RELEASE_ARCHIVE[[:blank:]]*=' \
$$HOME/.gnupg-autogen.rc|cut -d= -f2|xargs);\
if [ -z "$$x" ]; then \
echo "error: RELEASE_ARCHIVE missing in ~/.gnupg-autogen.rc">&2; \
exit 2;\
fi;\
myarchive="$$x/$(RELEASE_ARCHIVE_SUFFIX)";\
x=$$(grep '^RELEASE_SIGNKEY=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
x=$$(grep '^[[:blank:]]*RELEASE_SIGNKEY[[:blank:]]*=' \
$$HOME/.gnupg-autogen.rc|cut -d= -f2|xargs);\
if [ -z "$$x" ]; then \
echo "error: RELEASE_SIGNKEY missing in ~/.gnupg-autogen.rc">&2; \
exit 2;\

87
NEWS
View File

@ -1,6 +1,53 @@
Noteworthy changes in version 2.4.4 (2024-01-25)
Noteworthy changes in version 2.5.0 (unreleased)
------------------------------------------------
Changes also found in 2.4.5:
Noteworthy changes in version 2.4.5 (2024-03-07)
------------------------------------------------
* gpg,gpgv: New option --assert-pubkey-algo. [T6946]
* gpg: Emit status lines for errors in the compression layer.
[T6977]
* gpg: Fix invocation with --trusted-keys and --no-options. [T7025]
* gpgsm: Allow for a longer salt in PKCS#12 files. [T6757]
* gpgtar: Make --status-fd=2 work on Windows. [T6961]
* scd: Support for the ACR-122U NFC reader. [rG1682ca9f01]
* scd: Suport D-TRUST ECC cards. [T7000,T7001]
* scd: Allow auto detaching of kernel drivers; can be disabled with
the new compatibility-flag ccid-no-auto-detach. [rGa1ea3b13e0]
* scd: Allow setting a PIN length of 6 also with a reset code for
openpgp cards. [T6843]
* agent: Allow GET_PASSPHRASE in restricted mode. [rGadf4db6e20]
* dirmngr: Trust system's root CAs for checking CRL issuers.
[T6963]
* dirmngr: Fix regression in 2.4.4 in fetching keys via hkps.
[T6997]
* gpg-wks-client: Make option --mirror work properly w/o specifying
domains. [rG37cc255e49]
* g13,gpg-wks-client: Allow command style options as in "g13 mount
foo". [rGa09157ccb2]
* Allow tilde expansion for the foo-program options. [T7017]
* Make the getswdb.sh tool usable outside the GnuPG tree.
Changes also found in 2.4.4:
* gpg: Do not keep an unprotected smartcard backup key on disk. See
https://gnupg.org/blog/20240125-smartcard-backup-key.html for a
security advisory. [T6944]
@ -100,11 +147,7 @@ Noteworthy changes in version 2.4.4 (2024-01-25)
* Improve the speedo build system for Unix. [T6710]
Release-info: https://dev.gnupg.org/T6578
Noteworthy changes in version 2.4.3 (2023-07-04)
------------------------------------------------
Changes also found in 2.4.3:
* gpg: Set default expiration date to 3 years. [T2701]
@ -153,12 +196,8 @@ Noteworthy changes in version 2.4.3 (2023-07-04)
* Fix garbled time output in non-English Windows. [T6741]
See-also: gnupg-announce/2023q3/000480.html
Release-info: https://dev.gnupg.org/T6509
Noteworthy changes in version 2.4.2 (2023-05-30)
------------------------------------------------
Changes also found in 2.4.2:
* gpg: Print a warning if no more encryption subkeys are left over
after changing the expiration date. [rGef2c3d50fa]
@ -180,8 +219,16 @@ Noteworthy changes in version 2.4.2 (2023-05-30)
* w32: Avoid using the VirtualStore. [T6403]
See-also: gnupg-announce/2023q2/000479.html
Release-info: https://dev.gnupg.org/T6506
Release dates of 2.4 versions
-----------------------------
Version 2.4.5 (2024-03-07) https://dev.gnupg.org/T6960
Version 2.4.4 (2024-01-25) https://dev.gnupg.org/T6578
Version 2.4.3 (2023-07-04) https://dev.gnupg.org/T6509
Version 2.4.2 (2023-05-30) https://dev.gnupg.org/T6506
Version 2.4.1 (2023-04-28) https://dev.gnupg.org/T6454
Version 2.4.0 (2022-12-16) https://dev.gnupg.org/T6302
Noteworthy changes in version 2.4.1 (2023-04-28)
@ -1391,7 +1438,7 @@ Noteworthy changes in version 2.3.0 (2021-04-07)
Changes also found in 2.2.12:
* tools: New commands --install-key and --remove-key for
gpg-wks-client. This allows to prepare a Web Key Directory on a
gpg-wks-client. This allows one to prepare a Web Key Directory on a
local file system for later upload to a web server.
* gpg: New --list-option "show-only-fpr-mbox". This makes the use
@ -1435,7 +1482,7 @@ Noteworthy changes in version 2.3.0 (2021-04-07)
query.
* gpg: Do not store the TOFU trust model in the trustdb. This
allows to enable or disable a TOFO model without triggering a
allows one to enable or disable a TOFO model without triggering a
trustdb rebuild. [#4134]
* scd: Fix cases of "Bad PIN" after using "forcesig". [#4177]
@ -1854,7 +1901,7 @@ Noteworthy changes in version 2.1.23 (2017-08-09)
to your gpg.conf.
* agent: Option --no-grab is now the default. The new option --grab
allows to revert this.
allows one to revert this.
* gpg: New import option "show-only".
@ -2984,7 +3031,7 @@ Noteworthy changes in version 2.1.0 (2014-11-06)
* gpg: Allow use of Brainpool curves.
* gpg: Accepts a space separated fingerprint as user ID. This
allows to copy and paste the fingerprint from the key listing.
allows one to copy and paste the fingerprint from the key listing.
* gpg: The hash algorithm is now printed for signature records in key
listings.
@ -3764,7 +3811,7 @@ Noteworthy changes in version 1.9.10 (2004-07-22)
* Fixed a serious bug in the checking of trusted root certificates.
* New configure option --enable-agent-pnly allows to build and
* New configure option --enable-agent-only allows one to build and
install just the agent.
* Fixed a problem with the log file handling.
@ -4159,7 +4206,7 @@ Noteworthy changes in version 1.1.92 (2002-09-11)
extension specified with --load-extension are checked, along
with their enclosing directories.
* The configure option --with-static-rnd=auto allows to build gpg
* The configure option --with-static-rnd=auto allows one to build gpg
with all available entropy gathering modules included. At
runtime the best usable one will be selected from the list
linux, egd, unix. This is also the default for systems lacking
@ -4542,7 +4589,7 @@ Noteworthy changes in version 1.0.2 (2000-07-12)
* New command --export-secret-subkeys which outputs the
the _primary_ key with it's secret parts deleted. This is
useful for automated decryption/signature creation as it
allows to keep the real secret primary key offline and
allows one to keep the real secret primary key offline and
thereby protecting the key certificates and allowing to
create revocations for the subkeys. See the FAQ for a
procedure to install such secret keys.

2
README
View File

@ -1,6 +1,6 @@
The GNU Privacy Guard
=======================
Version 2.4
Version 2.5 (devel)
Copyright 1997-2019 Werner Koch
Copyright 1998-2021 Free Software Foundation, Inc.

View File

@ -86,8 +86,8 @@ struct
/* Enable pinentry debugging (--debug 1024 should also be used). */
int debug_pinentry;
/* Filename of the program to start as pinentry. */
const char *pinentry_program;
/* Filename of the program to start as pinentry (malloced). */
char *pinentry_program;
/* Filename of the program to handle daemon tasks. */
const char *daemon_program[DAEMON_MAX_TYPE];
@ -288,8 +288,11 @@ struct server_control_s
unsigned int raw_value: 1;
unsigned int is_pss: 1; /* DATA holds PSS formated data. */
} digest;
unsigned int have_keygrip: 1;
unsigned int have_keygrip1: 1;
unsigned char keygrip[20];
int have_keygrip;
unsigned char keygrip1[20]; /* Another keygrip for hybrid crypto. */
/* A flag to enable a hack to send the PKAUTH command instead of the
PKSIGN command to the scdaemon. */
@ -428,6 +431,7 @@ void *get_agent_daemon_notify_event (void);
#endif
void agent_sighup_action (void);
int map_pk_openpgp_to_gcry (int openpgp_algo);
void agent_kick_the_loop (void);
/*-- command.c --*/
gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid,
@ -533,7 +537,7 @@ int agent_clear_passphrase (ctrl_t ctrl,
/*-- cache.c --*/
void initialize_module_cache (void);
void deinitialize_module_cache (void);
void agent_cache_housekeeping (void);
struct timespec *agent_cache_expiration (void);
void agent_flush_cache (int pincache_only);
int agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
const char *data, int ttl);
@ -556,6 +560,18 @@ gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
const unsigned char *ciphertext, size_t ciphertextlen,
membuf_t *outbuf, int *r_padding);
enum kemids
{
KEM_PQC_PGP,
KEM_PGP,
KEM_CMS
};
gpg_error_t agent_kem_decrypt (ctrl_t ctrl, const char *desc_text, int kemid,
const unsigned char *ct, size_t ctlen,
const unsigned char *option, size_t optionlen,
membuf_t *outbuf);
/*-- genkey.c --*/
#define CHECK_CONSTRAINTS_NOT_EMPTY 1
#define CHECK_CONSTRAINTS_NEW_SYMKEY 2
@ -689,6 +705,9 @@ gpg_error_t divert_writekey (ctrl_t ctrl, int force, const char *serialno,
const char *keyref,
const char *keydata, size_t keydatalen);
gpg_error_t agent_card_ecc_kem (ctrl_t ctrl, const unsigned char *ecc_ct,
size_t ecc_point_len, unsigned char *ecc_ecdh);
/*-- call-daemon.c --*/
gpg_error_t daemon_start (enum daemon_type type, ctrl_t ctrl);
assuan_context_t daemon_type_ctx (enum daemon_type type, ctrl_t ctrl);
@ -737,6 +756,7 @@ int agent_card_pkdecrypt (ctrl_t ctrl,
const char *desc_text,
const unsigned char *indata, size_t indatalen,
char **r_buf, size_t *r_buflen, int *r_padding);
int agent_card_readcert (ctrl_t ctrl,
const char *id, char **r_buf, size_t *r_buflen);
int agent_card_readkey (ctrl_t ctrl, const char *id,
@ -758,7 +778,6 @@ void agent_card_free_keyinfo (struct card_key_info_s *l);
gpg_error_t agent_card_keyinfo (ctrl_t ctrl, const char *keygrip,
int cap, struct card_key_info_s **result);
/*-- learncard.c --*/
int agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force);

View File

@ -53,8 +53,20 @@ struct secret_data_s {
char data[1]; /* A string. */
};
/* The cache object. */
/* The type of cache object. */
typedef struct cache_item_s *ITEM;
/* The timer entry in a linked list. */
struct timer_s {
ITEM next;
int tv_sec;
int reason;
};
#define CACHE_EXPIRE_UNUSED 0
#define CACHE_EXPIRE_LAST_ACCESS 1
#define CACHE_EXPIRE_CREATION 2
/* The cache object. */
struct cache_item_s {
ITEM next;
time_t created;
@ -63,12 +75,18 @@ struct cache_item_s {
struct secret_data_s *pw;
cache_mode_t cache_mode;
int restricted; /* The value of ctrl->restricted is part of the key. */
struct timer_s t;
char key[1];
};
/* The cache himself. */
static ITEM thecache;
/* The timer list of expiration, in active. */
static ITEM the_timer_list;
/* Newly created entries, to be inserted into the timer list. */
static ITEM the_timer_list_new;
/* NULL or the last cache key stored by agent_store_cache_hit. */
static char *last_stored_cache_key;
@ -193,100 +211,302 @@ new_data (const char *string, struct secret_data_s **r_data)
}
/* Check whether there are items to expire. */
static void
housekeeping (void)
insert_to_timer_list_new (ITEM entry)
{
ITEM r, rprev;
entry->t.next = the_timer_list_new;
the_timer_list_new = entry;
}
/* Insert to the active timer list. */
static void
insert_to_timer_list (struct timespec *ts, ITEM entry)
{
ITEM e, eprev;
if (!the_timer_list || ts->tv_sec >= entry->t.tv_sec)
{
if (the_timer_list)
{
the_timer_list->t.tv_sec += ts->tv_sec - entry->t.tv_sec;
if (ts->tv_nsec >= 500000000)
the_timer_list->t.tv_sec++;
}
ts->tv_sec = entry->t.tv_sec;
ts->tv_nsec = 0;
entry->t.tv_sec = 0;
entry->t.next = the_timer_list;
the_timer_list = entry;
return;
}
entry->t.tv_sec -= ts->tv_sec;
eprev = NULL;
for (e = the_timer_list; e; e = e->t.next)
{
if (e->t.tv_sec > entry->t.tv_sec)
break;
eprev = e;
entry->t.tv_sec -= e->t.tv_sec;
}
entry->t.next = e;
if (e)
e->t.tv_sec -= entry->t.tv_sec;
if (eprev)
eprev->t.next = entry;
else
the_timer_list = entry;
}
static void
remove_from_timer_list (ITEM entry)
{
ITEM e, eprev;
eprev = NULL;
for (e = the_timer_list; e; e = e->t.next)
if (e != entry)
eprev = e;
else
{
if (e->t.next)
e->t.next->t.tv_sec += e->t.tv_sec;
if (eprev)
eprev->t.next = e->t.next;
else
the_timer_list = e->t.next;
break;
}
entry->t.next = NULL;
entry->t.tv_sec = 0;
}
static void
remove_from_timer_list_new (ITEM entry)
{
ITEM e, eprev;
eprev = NULL;
for (e = the_timer_list_new; e; e = e->t.next)
if (e != entry)
eprev = e;
else
{
if (eprev)
eprev->t.next = e->t.next;
else
the_timer_list_new = e->t.next;
break;
}
entry->t.next = NULL;
entry->t.tv_sec = 0;
}
static int
compute_expiration (ITEM r)
{
unsigned long maxttl;
time_t current = gnupg_get_time ();
time_t next;
/* First expire the actual data */
for (r=thecache; r; r = r->next)
if (r->cache_mode == CACHE_MODE_PIN)
return 0; /* Don't let it expire - scdaemon explicitly flushes them. */
if (!r->pw)
{
if (r->cache_mode == CACHE_MODE_PIN)
; /* Don't let it expire - scdaemon explicitly flushes them. */
else if (r->pw && r->ttl >= 0 && r->accessed + r->ttl < current)
{
if (DBG_CACHE)
log_debug (" expired '%s'.%d (%ds after last access)\n",
r->key, r->restricted, r->ttl);
release_data (r->pw);
r->pw = NULL;
r->accessed = current;
}
/* Expire an old and unused entry after 30 minutes. */
r->t.tv_sec = 60*30;
r->t.reason = CACHE_EXPIRE_UNUSED;
return 1;
}
/* Second, make sure that we also remove them based on the created
* stamp so that the user has to enter it from time to time. We
* don't do this for data items which are used to storage secrets in
* meory and are not user entered passphrases etc. */
for (r=thecache; r; r = r->next)
switch (r->cache_mode)
{
unsigned long maxttl;
switch (r->cache_mode)
{
case CACHE_MODE_DATA:
case CACHE_MODE_PIN:
continue; /* No MAX TTL here. */
case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break;
default: maxttl = opt.max_cache_ttl; break;
}
if (r->pw && r->created + maxttl < current)
{
if (DBG_CACHE)
log_debug (" expired '%s'.%d (%lus after creation)\n",
r->key, r->restricted, opt.max_cache_ttl);
release_data (r->pw);
r->pw = NULL;
r->accessed = current;
}
case CACHE_MODE_DATA:
case CACHE_MODE_PIN:
maxttl = 0; /* No MAX TTL here. */
break;
case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break;
default: maxttl = opt.max_cache_ttl; break;
}
/* Third, make sure that we don't have too many items in the list.
* Expire old and unused entries after 30 minutes. */
for (rprev=NULL, r=thecache; r; )
if (maxttl)
{
if (!r->pw && r->ttl >= 0 && r->accessed + 60*30 < current)
if (r->created + maxttl < current)
{
ITEM r2 = r->next;
if (DBG_CACHE)
log_debug (" removed '%s'.%d (mode %d) (slot not used for 30m)\n",
r->key, r->restricted, r->cache_mode);
xfree (r);
if (!rprev)
thecache = r2;
else
rprev->next = r2;
r = r2;
}
else
{
rprev = r;
r = r->next;
r->t.tv_sec = 0;
r->t.reason = CACHE_EXPIRE_CREATION;
return 1;
}
next = r->created + maxttl - current;
}
else
next = 0;
if (r->ttl >= 0 && (next == 0 || r->ttl < next))
{
r->t.tv_sec = r->ttl;
r->t.reason = CACHE_EXPIRE_LAST_ACCESS;
return 1;
}
if (next)
{
r->t.tv_sec = next;
r->t.reason = CACHE_EXPIRE_CREATION;
return 1;
}
return 0;
}
static void
update_expiration (ITEM entry, int is_new_entry)
{
if (!is_new_entry)
{
remove_from_timer_list (entry);
remove_from_timer_list_new (entry);
}
if (compute_expiration (entry))
{
insert_to_timer_list_new (entry);
agent_kick_the_loop ();
}
}
void
agent_cache_housekeeping (void)
/* Expire the cache entry. Returns 1 when the entry should be removed
* from the cache. */
static int
do_expire (ITEM e)
{
int res;
if (!e->pw)
/* Unused entry after 30 minutes. */
return 1;
if (DBG_CACHE)
log_debug ("agent_cache_housekeeping\n");
if (e->t.reason == CACHE_EXPIRE_LAST_ACCESS)
{
if (DBG_CACHE)
log_debug (" expired '%s'.%d (%ds after last access)\n",
e->key, e->restricted, e->ttl);
}
else
{
if (DBG_CACHE)
log_debug (" expired '%s'.%d (%lus after creation)\n",
e->key, e->restricted, opt.max_cache_ttl);
}
release_data (e->pw);
e->pw = NULL;
e->accessed = 0;
if (compute_expiration (e))
insert_to_timer_list_new (e);
return 0;
}
struct timespec *
agent_cache_expiration (void)
{
static struct timespec abstime;
static struct timespec timeout;
struct timespec *tp;
struct timespec curtime;
int res;
int expired = 0;
ITEM e, enext;
res = npth_mutex_lock (&cache_lock);
if (res)
log_fatal ("failed to acquire cache mutex: %s\n", strerror (res));
housekeeping ();
npth_clock_gettime (&curtime);
if (the_timer_list)
{
if (npth_timercmp (&abstime, &curtime, <))
expired = 1;
else
npth_timersub (&abstime, &curtime, &timeout);
}
if (expired && (e = the_timer_list) && e->t.tv_sec == 0)
{
the_timer_list = e->t.next;
e->t.next = NULL;
if (do_expire (e))
{
ITEM r, rprev;
if (DBG_CACHE)
log_debug (" removed '%s'.%d (mode %d) (slot not used for 30m)\n",
e->key, e->restricted, e->cache_mode);
rprev = NULL;
for (r = thecache; r; r = r->next)
if (r == e)
{
if (!rprev)
thecache = r->next;
else
rprev->next = r->next;
break;
}
else
rprev = r;
remove_from_timer_list_new (e);
xfree (e);
}
}
if (expired || !the_timer_list)
timeout.tv_sec = timeout.tv_nsec = 0;
for (e = the_timer_list_new; e; e = enext)
{
enext = e->t.next;
e->t.next = NULL;
insert_to_timer_list (&timeout, e);
}
the_timer_list_new = NULL;
if (!the_timer_list)
tp = NULL;
else
{
if (the_timer_list->t.tv_sec != 0)
{
timeout.tv_sec += the_timer_list->t.tv_sec;
the_timer_list->t.tv_sec = 0;
}
npth_timeradd (&timeout, &curtime, &abstime);
tp = &timeout;
}
res = npth_mutex_unlock (&cache_lock);
if (res)
log_fatal ("failed to release cache mutex: %s\n", strerror (res));
return tp;
}
@ -314,6 +534,7 @@ agent_flush_cache (int pincache_only)
release_data (r->pw);
r->pw = NULL;
r->accessed = 0;
update_expiration (r, 0);
}
}
@ -358,7 +579,6 @@ agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
if (DBG_CACHE)
log_debug ("agent_put_cache '%s'.%d (mode %d) requested ttl=%d\n",
key, restricted, cache_mode, ttl);
housekeeping ();
if (!ttl)
{
@ -410,6 +630,7 @@ agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
err = new_data (data, &r->pw);
if (err)
log_error ("error replacing cache item: %s\n", gpg_strerror (err));
update_expiration (r, 0);
}
}
else if (data) /* Insert. */
@ -431,6 +652,7 @@ agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
{
r->next = thecache;
thecache = r;
update_expiration (r, 1);
}
}
if (err)
@ -478,7 +700,6 @@ agent_get_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode)
log_debug ("agent_get_cache '%s'.%d (mode %d)%s ...\n",
key, restricted, cache_mode,
last_stored? " (stored cache key)":"");
housekeeping ();
for (r=thecache; r; r = r->next)
{
@ -500,7 +721,10 @@ agent_get_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode)
* below. Note also that we don't update the accessed time
* for data items. */
if (r->cache_mode != CACHE_MODE_DATA)
r->accessed = gnupg_get_time ();
{
r->accessed = gnupg_get_time ();
update_expiration (r, 0);
}
if (DBG_CACHE)
log_debug ("... hit\n");
if (r->pw->totallen < 32)

View File

@ -98,7 +98,6 @@ static npth_mutex_t start_daemon_lock;
struct wait_child_thread_parm_s
{
enum daemon_type type;
pid_t pid;
};
@ -109,54 +108,14 @@ wait_child_thread (void *arg)
int err;
struct wait_child_thread_parm_s *parm = arg;
enum daemon_type type = parm->type;
pid_t pid = parm->pid;
#ifndef HAVE_W32_SYSTEM
int wstatus;
#endif
const char *name = opt.daemon_program[type];
struct daemon_global_s *g = &daemon_global[type];
struct daemon_local_s *sl;
xfree (parm); /* We have copied all data to the stack. */
#ifdef HAVE_W32_SYSTEM
npth_unprotect ();
/* Note that although we use a pid_t here, it is actually a HANDLE. */
WaitForSingleObject ((HANDLE)pid, INFINITE);
npth_protect ();
assuan_pipe_wait_server_termination (g->primary_ctx, NULL, 0);
log_info ("daemon %s finished\n", name);
#else /* !HAVE_W32_SYSTEM*/
again:
npth_unprotect ();
err = waitpid (pid, &wstatus, 0);
npth_protect ();
if (err < 0)
{
if (errno == EINTR)
goto again;
log_error ("waitpid for %s failed: %s\n", name, strerror (errno));
return NULL;
}
else
{
if (WIFEXITED (wstatus))
log_info ("daemon %s finished (status %d)\n",
name, WEXITSTATUS (wstatus));
else if (WIFSIGNALED (wstatus))
log_info ("daemon %s killed by signal %d\n", name, WTERMSIG (wstatus));
else
{
if (WIFSTOPPED (wstatus))
log_info ("daemon %s stopped by signal %d\n",
name, WSTOPSIG (wstatus));
goto again;
}
assuan_set_flag (g->primary_ctx, ASSUAN_NO_WAITPID, 1);
}
#endif /*!HAVE_W32_SYSTEM*/
agent_flush_cache (1); /* Flush the PIN cache. */
@ -471,8 +430,8 @@ daemon_start (enum daemon_type type, ctrl_t ctrl)
char buf[100];
#ifdef HAVE_W32_SYSTEM
snprintf (buf, sizeof buf, "OPTION event-signal=%lx",
(unsigned long)get_agent_daemon_notify_event ());
snprintf (buf, sizeof buf, "OPTION event-signal=%p",
get_agent_daemon_notify_event ());
#else
snprintf (buf, sizeof buf, "OPTION event-signal=%d", SIGUSR2);
#endif
@ -496,7 +455,6 @@ daemon_start (enum daemon_type type, ctrl_t ctrl)
}
wctp->type = type;
wctp->pid = assuan_get_pid (g->primary_ctx);
err = npth_attr_init (&tattr);
if (!err)
{
@ -561,10 +519,9 @@ agent_daemon_dump_state (void)
for (i = 0; i < DAEMON_MAX_TYPE; i++) {
struct daemon_global_s *g = &daemon_global[i];
log_info ("%s: name %s primary_ctx=%p pid=%ld reusable=%d\n", __func__,
log_info ("%s: name %s primary_ctx=%p reusable=%d\n", __func__,
gnupg_module_name (daemon_modules[i]),
g->primary_ctx,
(long)assuan_get_pid (g->primary_ctx),
g->primary_ctx_reusable);
if (g->socket_name)
log_info ("%s: socket='%s'\n", __func__, g->socket_name);

View File

@ -128,8 +128,9 @@ initialize_module_call_pinentry (void)
void
agent_query_dump_state (void)
{
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
entry_ctx, (long)assuan_get_pid (entry_ctx), (void*)popup_tid);
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%lx\n",
entry_ctx, (long)assuan_get_pid (entry_ctx),
(unsigned long)popup_tid);
}
/* Called to make sure that a popup window owned by the current
@ -1288,8 +1289,6 @@ build_cmd_setdesc (char *line, size_t linelen, const char *desc)
static void *
watch_sock (void *arg)
{
pid_t pid = assuan_get_pid (entry_ctx);
while (1)
{
int err;
@ -1302,7 +1301,7 @@ watch_sock (void *arg)
FD_ZERO (&fdset);
FD_SET (FD2INT (sock), &fdset);
err = npth_select (FD2INT (sock)+1, &fdset, NULL, NULL, &timeout);
err = npth_select (FD2NUM (sock)+1, &fdset, NULL, NULL, &timeout);
if (err < 0)
{
@ -1317,17 +1316,7 @@ watch_sock (void *arg)
break;
}
if (pid == (pid_t)(-1))
; /* No pid available can't send a kill. */
#ifdef HAVE_W32_SYSTEM
/* Older versions of assuan set PID to 0 on Windows to indicate an
invalid value. */
else if (pid != (pid_t) INVALID_HANDLE_VALUE && pid != 0)
TerminateProcess ((HANDLE)pid, 1);
#else
else if (pid > 0)
kill (pid, SIGINT);
#endif
assuan_pipe_kill_server (entry_ctx);
return NULL;
}
@ -2124,7 +2113,6 @@ void
agent_popup_message_stop (ctrl_t ctrl)
{
int rc;
pid_t pid;
(void)ctrl;
@ -2137,26 +2125,10 @@ agent_popup_message_stop (ctrl_t ctrl)
return;
}
pid = assuan_get_pid (entry_ctx);
if (pid == (pid_t)(-1))
; /* No pid available can't send a kill. */
else if (popup_finished)
if (popup_finished)
; /* Already finished and ready for joining. */
#ifdef HAVE_W32_SYSTEM
/* Older versions of assuan set PID to 0 on Windows to indicate an
invalid value. */
else if (pid != (pid_t) INVALID_HANDLE_VALUE
&& pid != 0)
{
HANDLE process = (HANDLE) pid;
/* Arbitrary error code. */
TerminateProcess (process, 1);
}
#else
else if (pid > 0)
kill (pid, SIGINT);
#endif
else
assuan_pipe_kill_server (entry_ctx);
/* Now wait for the thread to terminate. */
rc = npth_join (popup_tid, NULL);

View File

@ -548,7 +548,8 @@ padding_info_cb (void *opaque, const char *line)
if ((s=has_leading_keyword (line, "PADDING")))
{
*r_padding = atoi (s);
if (r_padding)
*r_padding = atoi (s);
}
else if ((s=has_leading_keyword (line, "PINCACHE_PUT")))
err = handle_pincache_put (s);
@ -560,8 +561,8 @@ padding_info_cb (void *opaque, const char *line)
/* Decipher INDATA using the current card. Note that the returned
* value is not an s-expression but the raw data as returned by
* scdaemon. The padding information is stored at R_PADDING with -1
* for not known. DESC_TEXT is an additional parameter passed to
* GETPIN_CB. */
* for not known, when it's not NULL. DESC_TEXT is an additional
* parameter passed to GETPIN_CB. */
int
agent_card_pkdecrypt (ctrl_t ctrl,
const char *keyid,
@ -579,7 +580,8 @@ agent_card_pkdecrypt (ctrl_t ctrl,
size_t len;
*r_buf = NULL;
*r_padding = -1; /* Unknown. */
if (r_padding)
*r_padding = -1; /* Unknown. */
rc = start_scd (ctrl);
if (rc)
return rc;

View File

@ -3952,7 +3952,11 @@ start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
es_syshd_t syshd;
syshd.type = ES_SYSHD_SOCK;
#ifdef HAVE_SOCKET
syshd.u.sock = (SOCKET)sock_client;
#else
syshd.u.sock = sock_client;
#endif
get_client_info (sock_client, &peer_info);
ctrl->client_pid = peer_info.pid;

View File

@ -241,7 +241,7 @@ reset_notify (assuan_context_t ctx, char *line)
(void) line;
memset (ctrl->keygrip, 0, 20);
ctrl->have_keygrip = 0;
ctrl->have_keygrip = ctrl->have_keygrip1 = 0;
ctrl->digest.valuelen = 0;
xfree (ctrl->digest.data);
ctrl->digest.data = NULL;
@ -796,8 +796,8 @@ cmd_havekey (assuan_context_t ctx, char *line)
static const char hlp_sigkey[] =
"SIGKEY <hexstring_with_keygrip>\n"
"SETKEY <hexstring_with_keygrip>\n"
"SIGKEY [--another] <hexstring_with_keygrip>\n"
"SETKEY [--another] <hexstring_with_keygrip>\n"
"\n"
"Set the key used for a sign or decrypt operation.";
static gpg_error_t
@ -805,11 +805,17 @@ cmd_sigkey (assuan_context_t ctx, char *line)
{
int rc;
ctrl_t ctrl = assuan_get_pointer (ctx);
int opt_another;
rc = parse_keygrip (ctx, line, ctrl->keygrip);
opt_another = has_option (line, "--another");
line = skip_options (line);
rc = parse_keygrip (ctx, line, opt_another? ctrl->keygrip1 : ctrl->keygrip);
if (rc)
return rc;
ctrl->have_keygrip = 1;
if (opt_another)
ctrl->have_keygrip1 = 1;
else
ctrl->have_keygrip = 1;
return 0;
}
@ -1043,10 +1049,14 @@ cmd_pksign (assuan_context_t ctx, char *line)
static const char hlp_pkdecrypt[] =
"PKDECRYPT [<options>]\n"
"PKDECRYPT [--kem[=<kemid>] [<options>]\n"
"\n"
"Perform the actual decrypt operation. Input is not\n"
"sensitive to eavesdropping.";
"sensitive to eavesdropping.\n"
"If the --kem option is used, decryption is done with the KEM,\n"
"inquiring upper-layer option, when needed. KEMID can be\n"
"specified with --kem option; Valid value is: PQC-PGP, PGP, or CMS.\n"
"Default is PQC-PGP.";
static gpg_error_t
cmd_pkdecrypt (assuan_context_t ctx, char *line)
{
@ -1055,22 +1065,52 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
unsigned char *value;
size_t valuelen;
membuf_t outbuf;
int padding;
int padding = -1;
unsigned char *option = NULL;
size_t optionlen = 0;
const char *p;
int kemid = -1;
(void)line;
p = has_option_name (line, "--kem");
if (p)
{
kemid = KEM_PQC_PGP;
if (*p == '=')
{
p++;
if (!strcmp (p, "PQC-PGP"))
kemid = KEM_PQC_PGP;
else if (!strcmp (p, "PGP"))
kemid = KEM_PGP;
else if (!strcmp (p, "CMS"))
kemid = KEM_CMS;
else
return set_error (GPG_ERR_ASS_PARAMETER, "invalid KEM algorithm");
}
}
/* First inquire the data to decrypt */
rc = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%u", MAXLEN_CIPHERTEXT);
if (!rc)
rc = assuan_inquire (ctx, "CIPHERTEXT",
&value, &valuelen, MAXLEN_CIPHERTEXT);
if (!rc && kemid > KEM_PQC_PGP)
rc = assuan_inquire (ctx, "OPTION",
&option, &optionlen, MAXLEN_CIPHERTEXT);
if (rc)
return rc;
init_membuf (&outbuf, 512);
rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
value, valuelen, &outbuf, &padding);
if (kemid < 0)
rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
value, valuelen, &outbuf, &padding);
else
{
rc = agent_kem_decrypt (ctrl, ctrl->server_local->keydesc, kemid,
value, valuelen, option, optionlen, &outbuf);
xfree (option);
}
xfree (value);
if (rc)
clear_outbuf (&outbuf);
@ -1418,7 +1458,9 @@ cmd_readkey (assuan_context_t ctx, char *line)
goto leave;
rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
if (!rc)
if (rc)
goto leave;
else
{
if (opt_format_ssh)
{
@ -1988,9 +2030,6 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
struct pin_entry_info_s *pi2 = NULL;
int is_generated;
if (ctrl->restricted)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
opt_data = has_option (line, "--data");
opt_check = has_option (line, "--check");
opt_no_ask = has_option (line, "--no-ask");
@ -2039,7 +2078,9 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
if (!desc)
return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
if (!strcmp (cacheid, "X"))
/* The only limitation in restricted mode is that we don't consider
* the cache. */
if (ctrl->restricted || !strcmp (cacheid, "X"))
cacheid = NULL;
if (!strcmp (errtext, "X"))
errtext = NULL;
@ -2121,7 +2162,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
entry_errtext = NULL;
is_generated = !!(pi->status & PINENTRY_STATUS_PASSWORD_GENERATED);
/* We don't allow an empty passpharse in this mode. */
/* We don't allow an empty passphrase in this mode. */
if (!is_generated
&& check_passphrase_constraints (ctrl, pi->pin,
pi->constraints_flags,

View File

@ -1384,6 +1384,17 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
err = gcry_sexp_extract_param (list, NULL, format,
array+0, array+1, NULL);
}
else if ( !strcmp (name, (algoname = "kyber512"))
|| !strcmp (name, (algoname = "kyber768"))
|| !strcmp (name, (algoname = "kyber1024")))
{
format = "/ps?";
elems = "ps?";
npkey = 1;
nskey = 2;
err = gcry_sexp_extract_param (list, NULL, format,
array+0, array+1, NULL);
}
else
{
err = gpg_error (GPG_ERR_PUBKEY_ALGO);

View File

@ -377,10 +377,10 @@ divert_pksign (ctrl_t ctrl, const unsigned char *grip,
}
/* Decrypt the value given asn an S-expression in CIPHER using the
/* Decrypt the value given as an s-expression in CIPHER using the
key identified by SHADOW_INFO and return the plaintext in an
allocated buffer in R_BUF. The padding information is stored at
R_PADDING with -1 for not known. */
R_PADDING with -1 for not known, when it's not NULL. */
int
divert_pkdecrypt (ctrl_t ctrl,
const unsigned char *grip,
@ -399,7 +399,8 @@ divert_pkdecrypt (ctrl_t ctrl,
bin2hex (grip, 20, hexgrip);
*r_padding = -1;
if (r_padding)
*r_padding = -1;
s = cipher;
if (*s != '(')
return gpg_error (GPG_ERR_INV_SEXP);
@ -485,6 +486,34 @@ divert_pkdecrypt (ctrl_t ctrl,
return rc;
}
gpg_error_t
agent_card_ecc_kem (ctrl_t ctrl, const unsigned char *ecc_ct,
size_t ecc_point_len, unsigned char *ecc_ecdh)
{
gpg_error_t err = 0;
char *ecdh = NULL;
size_t len;
int rc;
rc = agent_card_pkdecrypt (ctrl, ctrl->keygrip, getpin_cb, ctrl, NULL,
ecc_ct, ecc_point_len, &ecdh, &len, NULL);
if (rc)
return rc;
if (len != ecc_point_len)
{
if (opt.verbose)
log_info ("%s: ECC result length invalid (%zu != %zu)\n",
__func__, len, ecc_point_len);
return gpg_error (GPG_ERR_INV_DATA);
}
else
memcpy (ecc_ecdh, ecdh, len);
xfree (ecdh);
return err;
}
gpg_error_t
divert_writekey (ctrl_t ctrl, int force, const char *serialno,

View File

@ -106,7 +106,8 @@ divert_tpm2_pkdecrypt (ctrl_t ctrl,
const unsigned char *s;
size_t n;
*r_padding = -1;
if (r_padding)
*r_padding = -1;
s = cipher;
if (*s != '(')
@ -125,7 +126,8 @@ divert_tpm2_pkdecrypt (ctrl_t ctrl,
return gpg_error (GPG_ERR_INV_SEXP);
if (smatch (&s, n, "rsa"))
{
*r_padding = 0;
if (r_padding)
*r_padding = 0;
if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
s++;

View File

@ -161,7 +161,7 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
const char *pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CHECK_PATTERN);
estream_t stream_to_check_pattern = NULL;
const char *argv[10];
pid_t pid;
gnupg_process_t proc;
int result, i;
const char *pattern;
char *patternfname;
@ -204,11 +204,17 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
argv[i] = NULL;
log_assert (i < sizeof argv);
if (gnupg_spawn_process (pgmname, argv, NULL, 0,
&stream_to_check_pattern, NULL, NULL, &pid))
if (gnupg_process_spawn (pgmname, argv,
GNUPG_PROCESS_STDIN_PIPE,
NULL, NULL, &proc))
result = 1; /* Execute error - assume password should no be used. */
else
{
int status;
gnupg_process_get_streams (proc, 0, &stream_to_check_pattern,
NULL, NULL);
es_set_binary (stream_to_check_pattern);
if (es_fwrite (pw, strlen (pw), 1, stream_to_check_pattern) != 1)
{
@ -219,11 +225,13 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
else
es_fflush (stream_to_check_pattern);
es_fclose (stream_to_check_pattern);
if (gnupg_wait_process (pgmname, pid, 1, NULL))
gnupg_process_wait (proc, 1);
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &status);
if (status)
result = 1; /* Helper returned an error - probably a match. */
else
result = 0; /* Success; i.e. no match. */
gnupg_release_process (pid);
gnupg_process_release (proc);
}
xfree (patternfname);

View File

@ -341,15 +341,13 @@ static struct debug_flags_s debug_flags [] =
#define MIN_PASSPHRASE_NONALPHA (1)
#define MAX_PASSPHRASE_DAYS (0)
/* The timer tick used for housekeeping stuff. Note that on Windows
* we use a SetWaitableTimer seems to signal earlier than about 2
* seconds. Thus we use 4 seconds on all platforms.
* CHECK_OWN_SOCKET_INTERVAL defines how often we check
* our own socket in standard socket mode. If that value is 0 we
* don't check at all. All values are in seconds. */
#define TIMERTICK_INTERVAL (4)
/* CHECK_OWN_SOCKET_INTERVAL defines how often we check our own socket
* in standard socket mode. If that value is 0 we don't check at all.
* Values is in seconds. */
#define CHECK_OWN_SOCKET_INTERVAL (60)
/* CHECK_PROBLEMS_INTERVAL defines how often we check the existence of
* parent process and homedir. Value is in seconds. */
#define CHECK_PROBLEMS_INTERVAL (4)
/* Flag indicating that the ssh-agent subsystem has been enabled. */
static int ssh_support;
@ -384,9 +382,6 @@ static int startup_signal_mask_valid;
/* Flag to indicate that a shutdown was requested. */
static int shutdown_pending;
/* Counter for the currently running own socket checks. */
static int check_own_socket_running;
/* Flags to indicate that check_own_socket shall not be called. */
static int disable_check_own_socket;
@ -396,6 +391,12 @@ static int is_supervised;
/* Flag indicating to start the daemon even if one already runs. */
static int steal_socket;
/* Flag to monitor problems. */
static int problem_detected;
#define AGENT_PROBLEM_SOCKET_TAKEOVER (1 << 0)
#define AGENT_PROBLEM_PARENT_HAS_GONE (1 << 1)
#define AGENT_PROBLEM_HOMEDIR_REMOVED (1 << 2)
/* Flag to inhibit socket removal in cleanup. */
static int inhibit_socket_removal;
@ -432,6 +433,17 @@ static assuan_sock_nonce_t socket_nonce_ssh;
* Let's try this as default. Change at runtime with --listen-backlog. */
static int listen_backlog = 64;
#ifdef HAVE_W32_SYSTEM
/* The event to break the select call. */
static HANDLE the_event2;
#elif defined(HAVE_PSELECT_NO_EINTR)
/* An FD to break the select call. */
static int event_pipe_fd;
#else
/* PID of the main thread. */
static pid_t main_thread_pid;
#endif
/* Default values for options passed to the pinentry. */
static char *default_display;
static char *default_ttyname;
@ -452,9 +464,14 @@ static const char *debug_level;
the log file after a SIGHUP if it didn't changed. Malloced. */
static char *current_logfile;
/* The handle_tick() function may test whether a parent is still
* running. We record the PID of the parent here or -1 if it should
* be watched. */
#ifdef HAVE_W32_SYSTEM
#define HAVE_PARENT_PID_SUPPORT 0
#else
#define HAVE_PARENT_PID_SUPPORT 1
#endif
/* The check_others_thread() function may test whether a parent is
* still running. We record the PID of the parent here or -1 if it
* should be watched. */
static pid_t parent_pid = (pid_t)(-1);
/* This flag is true if the inotify mechanism for detecting the
@ -462,11 +479,6 @@ static pid_t parent_pid = (pid_t)(-1);
* alternative but portable stat based check. */
static int have_homedir_inotify;
/* Depending on how gpg-agent was started, the homedir inotify watch
* may not be reliable. This flag is set if we assume that inotify
* works reliable. */
static int reliable_homedir_inotify;
/* Number of active connections. */
static int active_connections;
@ -516,13 +528,13 @@ static void agent_deinit_default_ctrl (ctrl_t ctrl);
static void handle_connections (gnupg_fd_t listen_fd,
gnupg_fd_t listen_fd_extra,
gnupg_fd_t listen_fd_browser,
gnupg_fd_t listen_fd_ssh);
static void check_own_socket (void);
gnupg_fd_t listen_fd_ssh,
int reliable_homedir_inotify);
static int check_for_running_agent (int silent);
/* Pth wrapper function definitions. */
ASSUAN_SYSTEM_NPTH_IMPL;
#if CHECK_OWN_SOCKET_INTERVAL > 0
static void *check_own_socket_thread (void *arg);
#endif
static void *check_others_thread (void *arg);
/*
Functions.
@ -864,6 +876,7 @@ parse_rereadable_options (gpgrt_argparse_t *pargs, int reread)
opt.debug = 0;
opt.no_grab = 1;
opt.debug_pinentry = 0;
xfree (opt.pinentry_program);
opt.pinentry_program = NULL;
opt.pinentry_touch_file = NULL;
xfree (opt.pinentry_invisible_char);
@ -924,7 +937,10 @@ parse_rereadable_options (gpgrt_argparse_t *pargs, int reread)
case oNoGrab: opt.no_grab |= 1; break;
case oGrab: opt.no_grab |= 2; break;
case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
case oPinentryProgram:
xfree (opt.pinentry_program);
opt.pinentry_program = make_filename_try (pargs->r.ret_str, NULL);
break;
case oPinentryTouchFile: opt.pinentry_touch_file = pargs->r.ret_str; break;
case oPinentryInvisibleChar:
xfree (opt.pinentry_invisible_char);
@ -1046,6 +1062,7 @@ thread_init_once (void)
* initialized and thus Libgcrypt could not set its system call
* clamp. */
gcry_control (GCRYCTL_REINIT_SYSCALL_CLAMP, 0, 0);
assuan_control (ASSUAN_CONTROL_REINIT_SYSCALL_CLAMP, NULL);
}
@ -1053,7 +1070,6 @@ static void
initialize_modules (void)
{
thread_init_once ();
assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
initialize_module_cache ();
initialize_module_call_pinentry ();
initialize_module_daemon ();
@ -1081,6 +1097,7 @@ main (int argc, char **argv)
int gpgconf_list = 0;
gpg_error_t err;
struct assuan_malloc_hooks malloc_hooks;
int reliable_homedir_inotify = 1;
early_system_init ();
@ -1113,7 +1130,6 @@ main (int argc, char **argv)
assuan_set_malloc_hooks (&malloc_hooks);
assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
assuan_sock_init ();
assuan_sock_set_system_hooks (ASSUAN_SYSTEM_NPTH);
setup_libassuan_logging (&opt.debug, NULL);
setup_libgcrypt_logging ();
@ -1579,7 +1595,7 @@ main (int argc, char **argv)
log_info ("listening on: std=%d extra=%d browser=%d ssh=%d\n",
fd, fd_extra, fd_browser, fd_ssh);
handle_connections (fd, fd_extra, fd_browser, fd_ssh);
handle_connections (fd, fd_extra, fd_browser, fd_ssh, 1);
#endif /*!HAVE_W32_SYSTEM*/
}
else if (!is_daemon)
@ -1807,14 +1823,14 @@ main (int argc, char **argv)
log_get_prefix (&oldflags);
log_set_prefix (NULL, oldflags | GPGRT_LOG_RUN_DETACHED);
opt.running_detached = 1;
/* Unless we are running with a program given on the command
* line we can assume that the inotify things works and thus
* we can avoid the regular stat calls. */
if (!argc)
reliable_homedir_inotify = 1;
}
/* When we are running with a program given on the command
* line, the inotify things may not work well and thus
* we cannot avoid the regular stat calls. */
if (argc)
reliable_homedir_inotify = 0;
{
struct sigaction sa;
@ -1833,7 +1849,8 @@ main (int argc, char **argv)
}
log_info ("%s %s started\n", gpgrt_strusage(11), gpgrt_strusage(13) );
handle_connections (fd, fd_extra, fd_browser, fd_ssh);
handle_connections (fd, fd_extra, fd_browser, fd_ssh,
reliable_homedir_inotify);
assuan_sock_close (fd);
}
@ -2135,39 +2152,45 @@ get_agent_active_connection_count (void)
notification event. Calling it the first time creates that
event. */
#if defined(HAVE_W32_SYSTEM)
static void *
create_an_event (void)
{
HANDLE h, h2;
SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
/* We need to use a manual reset event object due to the way our
w32-pth wait function works: If we would use an automatic
reset event we are not able to figure out which handle has
been signaled because at the time we single out the signaled
handles using WFSO the event has already been reset due to
the WFMO. */
h = CreateEvent (&sa, TRUE, FALSE, NULL);
if (!h)
log_error ("can't create an event: %s\n", w32_strerror (-1) );
else if (!DuplicateHandle (GetCurrentProcess(), h,
GetCurrentProcess(), &h2,
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
{
log_error ("setting synchronize for an event failed: %s\n",
w32_strerror (-1) );
CloseHandle (h);
}
else
{
CloseHandle (h);
return h2;
}
return INVALID_HANDLE_VALUE;
}
void *
get_agent_daemon_notify_event (void)
{
static HANDLE the_event = INVALID_HANDLE_VALUE;
if (the_event == INVALID_HANDLE_VALUE)
{
HANDLE h, h2;
SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
/* We need to use a manual reset event object due to the way our
w32-pth wait function works: If we would use an automatic
reset event we are not able to figure out which handle has
been signaled because at the time we single out the signaled
handles using WFSO the event has already been reset due to
the WFMO. */
h = CreateEvent (&sa, TRUE, FALSE, NULL);
if (!h)
log_error ("can't create scd notify event: %s\n", w32_strerror (-1) );
else if (!DuplicateHandle (GetCurrentProcess(), h,
GetCurrentProcess(), &h2,
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
{
log_error ("setting synchronize for scd notify event failed: %s\n",
w32_strerror (-1) );
CloseHandle (h);
}
else
{
CloseHandle (h);
the_event = h2;
}
}
the_event = create_an_event ();
return the_event;
}
@ -2424,57 +2447,6 @@ create_directories (void)
}
/* This is the worker for the ticker. It is called every few seconds
and may only do fast operations. */
static void
handle_tick (void)
{
static time_t last_minute;
struct stat statbuf;
if (!last_minute)
last_minute = time (NULL);
/* If we are running as a child of another process, check whether
the parent is still alive and shutdown if not. */
#ifndef HAVE_W32_SYSTEM
if (parent_pid != (pid_t)(-1))
{
if (kill (parent_pid, 0))
{
shutdown_pending = 2;
log_info ("parent process died - shutting down\n");
log_info ("%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13));
cleanup ();
agent_exit (0);
}
}
#endif /*HAVE_W32_SYSTEM*/
/* Code to be run from time to time. */
#if CHECK_OWN_SOCKET_INTERVAL > 0
if (last_minute + CHECK_OWN_SOCKET_INTERVAL <= time (NULL))
{
check_own_socket ();
last_minute = time (NULL);
}
#endif
/* Need to check for expired cache entries. */
agent_cache_housekeeping ();
/* Check whether the homedir is still available. */
if (!shutdown_pending
&& (!have_homedir_inotify || !reliable_homedir_inotify)
&& gnupg_stat (gnupg_homedir (), &statbuf) && errno == ENOENT)
{
shutdown_pending = 1;
log_info ("homedir has been removed - shutting down\n");
}
}
/* A global function which allows us to call the reload stuff from
other places too. This is only used when build for W32. */
void
@ -2533,6 +2505,11 @@ handle_signal (int signo)
agent_sigusr2_action ();
break;
case SIGCONT:
/* Do nothing, but break the syscall. */
log_debug ("SIGCONT received - breaking select\n");
break;
case SIGTERM:
if (!shutdown_pending)
log_info ("SIGTERM received - shutting down ...\n");
@ -2570,7 +2547,7 @@ check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce)
if (assuan_sock_check_nonce (ctrl->thread_startup.fd, nonce))
{
log_info (_("error reading nonce on fd %d: %s\n"),
FD2INT(ctrl->thread_startup.fd), strerror (errno));
FD_DBG (ctrl->thread_startup.fd), strerror (errno));
assuan_sock_close (ctrl->thread_startup.fd);
xfree (ctrl);
return -1;
@ -2870,12 +2847,12 @@ do_start_connection_thread (ctrl_t ctrl)
agent_init_default_ctrl (ctrl);
if (opt.verbose > 1 && !DBG_IPC)
log_info (_("handler 0x%lx for fd %d started\n"),
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
(unsigned long) npth_self(), FD_DBG (ctrl->thread_startup.fd));
start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd);
if (opt.verbose > 1 && !DBG_IPC)
log_info (_("handler 0x%lx for fd %d terminated\n"),
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
(unsigned long) npth_self(), FD_DBG (ctrl->thread_startup.fd));
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
@ -2950,12 +2927,12 @@ start_connection_thread_ssh (void *arg)
agent_init_default_ctrl (ctrl);
if (opt.verbose)
log_info (_("ssh handler 0x%lx for fd %d started\n"),
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
(unsigned long) npth_self(), FD_DBG (ctrl->thread_startup.fd));
start_command_handler_ssh (ctrl, ctrl->thread_startup.fd);
if (opt.verbose)
log_info (_("ssh handler 0x%lx for fd %d terminated\n"),
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
(unsigned long) npth_self(), FD_DBG (ctrl->thread_startup.fd));
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
@ -2964,13 +2941,36 @@ start_connection_thread_ssh (void *arg)
}
void
agent_kick_the_loop (void)
{
/* Kick the select loop. */
#ifdef HAVE_W32_SYSTEM
int ret = SetEvent (the_event2);
if (ret == 0)
log_error ("SetEvent for agent_kick_the_loop failed: %s\n",
w32_strerror (-1));
#else
# ifdef HAVE_PSELECT_NO_EINTR
write (event_pipe_fd, "", 1);
# else
int ret = kill (main_thread_pid, SIGCONT);
if (ret < 0)
log_error ("sending signal for agent_kick_the_loop failed: %s\n",
gpg_strerror (gpg_error_from_syserror ()));
# endif
#endif
}
/* Connection handler loop. Wait for connection requests and spawn a
thread after accepting a connection. */
static void
handle_connections (gnupg_fd_t listen_fd,
gnupg_fd_t listen_fd_extra,
gnupg_fd_t listen_fd_browser,
gnupg_fd_t listen_fd_ssh)
gnupg_fd_t listen_fd_ssh,
int reliable_homedir_inotify)
{
gpg_error_t err;
npth_attr_t tattr;
@ -2981,12 +2981,15 @@ handle_connections (gnupg_fd_t listen_fd,
gnupg_fd_t fd;
int nfd;
int saved_errno;
struct timespec abstime;
struct timespec curtime;
struct timespec timeout;
struct timespec *tp;
#ifdef HAVE_W32_SYSTEM
HANDLE events[2];
HANDLE events[3];
unsigned int events_set;
#else
int signo;
# ifdef HAVE_PSELECT_NO_EINTR
int pipe_fd[2];
# endif
#endif
int sock_inotify_fd = -1;
int home_inotify_fd = -1;
@ -3014,11 +3017,24 @@ handle_connections (gnupg_fd_t listen_fd,
npth_sigev_add (SIGUSR1);
npth_sigev_add (SIGUSR2);
npth_sigev_add (SIGINT);
npth_sigev_add (SIGCONT);
npth_sigev_add (SIGTERM);
npth_sigev_fini ();
# ifdef HAVE_PSELECT_NO_EINTR
ret = gnupg_create_pipe (pipe_fd);
if (ret)
{
log_error ("pipe creation failed: %s\n", gpg_strerror (ret));
return;
}
event_pipe_fd = pipe_fd[1];
# else
main_thread_pid = getpid ();
# endif
#else
events[0] = get_agent_daemon_notify_event ();
events[1] = INVALID_HANDLE_VALUE;
events[1] = the_event2 = create_an_event ();
events[2] = INVALID_HANDLE_VALUE;
#endif
if (disable_check_own_socket)
@ -3030,7 +3046,7 @@ handle_connections (gnupg_fd_t listen_fd,
gpg_strerror (err));
}
if (disable_check_own_socket)
if (!reliable_homedir_inotify)
home_inotify_fd = -1;
else if ((err = gnupg_inotify_watch_delete_self (&home_inotify_fd,
gnupg_homedir ())))
@ -3042,6 +3058,27 @@ handle_connections (gnupg_fd_t listen_fd,
else
have_homedir_inotify = 1;
#if CHECK_OWN_SOCKET_INTERVAL > 0
if (!disable_check_own_socket && sock_inotify_fd == -1)
{
npth_t thread;
err = npth_create (&thread, &tattr, check_own_socket_thread, NULL);
if (err)
log_error ("error spawning check_own_socket_thread: %s\n", strerror (err));
}
#endif
if ((HAVE_PARENT_PID_SUPPORT && parent_pid != (pid_t)(-1))
|| !have_homedir_inotify)
{
npth_t thread;
err = npth_create (&thread, &tattr, check_others_thread, NULL);
if (err)
log_error ("error spawning check_others_thread: %s\n", strerror (err));
}
/* On Windows we need to fire up a separate thread to listen for
requests from Putty (an SSH client), so we can replace Putty's
Pageant (its ssh-agent implementation). */
@ -3071,24 +3108,24 @@ handle_connections (gnupg_fd_t listen_fd,
FD_ZERO (&fdset);
FD_SET (FD2INT (listen_fd), &fdset);
nfd = FD2INT (listen_fd);
nfd = FD2NUM (listen_fd);
if (listen_fd_extra != GNUPG_INVALID_FD)
{
FD_SET ( FD2INT(listen_fd_extra), &fdset);
if (FD2INT (listen_fd_extra) > nfd)
nfd = FD2INT (listen_fd_extra);
nfd = FD2NUM (listen_fd_extra);
}
if (listen_fd_browser != GNUPG_INVALID_FD)
{
FD_SET ( FD2INT(listen_fd_browser), &fdset);
if (FD2INT (listen_fd_browser) > nfd)
nfd = FD2INT (listen_fd_browser);
nfd = FD2NUM (listen_fd_browser);
}
if (listen_fd_ssh != GNUPG_INVALID_FD)
{
FD_SET ( FD2INT(listen_fd_ssh), &fdset);
if (FD2INT (listen_fd_ssh) > nfd)
nfd = FD2INT (listen_fd_ssh);
nfd = FD2NUM (listen_fd_ssh);
}
if (sock_inotify_fd != -1)
{
@ -3108,15 +3145,12 @@ handle_connections (gnupg_fd_t listen_fd,
listentbl[2].l_fd = listen_fd_browser;
listentbl[3].l_fd = listen_fd_ssh;
npth_clock_gettime (&abstime);
abstime.tv_sec += TIMERTICK_INTERVAL;
for (;;)
{
/* Shutdown test. */
if (shutdown_pending)
{
if (active_connections == 0)
if (active_connections == 0 || is_supervised)
break; /* ready */
/* Do not accept new connections but keep on running the
@ -3145,28 +3179,23 @@ handle_connections (gnupg_fd_t listen_fd,
thus a simple assignment is fine to copy the entire set. */
read_fdset = fdset;
npth_clock_gettime (&curtime);
if (!(npth_timercmp (&curtime, &abstime, <)))
{
/* Timeout. */
handle_tick ();
npth_clock_gettime (&abstime);
abstime.tv_sec += TIMERTICK_INTERVAL;
}
npth_timersub (&abstime, &curtime, &timeout);
#ifdef HAVE_PSELECT_NO_EINTR
FD_SET (pipe_fd[0], &read_fdset);
if (nfd < pipe_fd[0])
nfd = pipe_fd[0];
#endif
tp = agent_cache_expiration ();
#ifndef HAVE_W32_SYSTEM
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, tp,
npth_sigev_sigmask ());
saved_errno = errno;
{
int signo;
while (npth_sigev_get_pending (&signo))
handle_signal (signo);
}
while (npth_sigev_get_pending (&signo))
handle_signal (signo);
#else
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, tp,
events, &events_set);
saved_errno = errno;
@ -3182,11 +3211,47 @@ handle_connections (gnupg_fd_t listen_fd,
gnupg_sleep (1);
continue;
}
#ifndef HAVE_W32_SYSTEM
if ((problem_detected & AGENT_PROBLEM_PARENT_HAS_GONE))
{
shutdown_pending = 2;
log_info ("parent process died - shutting down\n");
log_info ("%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13));
cleanup ();
agent_exit (0);
}
#endif
if ((problem_detected & AGENT_PROBLEM_SOCKET_TAKEOVER))
{
/* We may not remove the socket as it is now in use by another
server. */
inhibit_socket_removal = 1;
shutdown_pending = 2;
log_info ("this process is useless - shutting down\n");
}
if ((problem_detected & AGENT_PROBLEM_HOMEDIR_REMOVED))
{
shutdown_pending = 1;
log_info ("homedir has been removed - shutting down\n");
}
if (ret <= 0)
/* Interrupt or timeout. Will be handled when calculating the
next timeout. */
continue;
#ifdef HAVE_PSELECT_NO_EINTR
if (FD_ISSET (pipe_fd[0], &read_fdset))
{
char buf[256];
read (pipe_fd[0], buf, sizeof buf);
}
#endif
/* The inotify fds are set even when a shutdown is pending (see
* above). So we must handle them in any case. To avoid that
* they trigger a second time we close them immediately. */
@ -3194,7 +3259,10 @@ handle_connections (gnupg_fd_t listen_fd,
&& FD_ISSET (sock_inotify_fd, &read_fdset)
&& gnupg_inotify_has_name (sock_inotify_fd, GPG_AGENT_SOCK_NAME))
{
shutdown_pending = 1;
/* We may not remove the socket (if any), as it may be now
in use by another server. */
inhibit_socket_removal = 1;
shutdown_pending = 2;
close (sock_inotify_fd);
sock_inotify_fd = -1;
log_info ("socket file has been removed - shutting down\n");
@ -3223,8 +3291,8 @@ handle_connections (gnupg_fd_t listen_fd,
continue;
plen = sizeof paddr;
fd = INT2FD (npth_accept (FD2INT(listentbl[idx].l_fd),
(struct sockaddr *)&paddr, &plen));
fd = assuan_sock_accept (listentbl[idx].l_fd,
(struct sockaddr *)&paddr, &plen);
if (fd == GNUPG_INVALID_FD)
{
log_error ("accept failed for %s: %s\n",
@ -3264,13 +3332,21 @@ handle_connections (gnupg_fd_t listen_fd,
close (sock_inotify_fd);
if (home_inotify_fd != -1)
close (home_inotify_fd);
#ifdef HAVE_W32_SYSTEM
if (the_event2 != INVALID_HANDLE_VALUE)
CloseHandle (the_event2);
#endif
#ifdef HAVE_PSELECT_NO_EINTR
close (pipe_fd[0]);
close (pipe_fd[1]);
#endif
cleanup ();
log_info (_("%s %s stopped\n"), gpgrt_strusage(11), gpgrt_strusage(13));
npth_attr_destroy (&tattr);
}
#if CHECK_OWN_SOCKET_INTERVAL > 0
/* Helper for check_own_socket. */
static gpg_error_t
check_own_socket_pid_cb (void *opaque, const void *buffer, size_t length)
@ -3281,20 +3357,18 @@ check_own_socket_pid_cb (void *opaque, const void *buffer, size_t length)
}
/* The thread running the actual check. We need to run this in a
separate thread so that check_own_thread can be called from the
timer tick. */
static void *
check_own_socket_thread (void *arg)
/* Check whether we are still listening on our own socket. In case
another gpg-agent process started after us has taken ownership of
our socket, we would linger around without any real task. Thus we
better check once in a while whether we are really needed. */
static int
do_check_own_socket (const char *sockname)
{
int rc;
char *sockname = arg;
assuan_context_t ctx = NULL;
membuf_t mb;
char *buffer;
check_own_socket_running++;
rc = assuan_new (&ctx);
if (rc)
{
@ -3332,58 +3406,78 @@ check_own_socket_thread (void *arg)
xfree (buffer);
leave:
xfree (sockname);
if (ctx)
assuan_release (ctx);
if (rc)
{
/* We may not remove the socket as it is now in use by another
server. */
inhibit_socket_removal = 1;
shutdown_pending = 2;
log_info ("this process is useless - shutting down\n");
}
check_own_socket_running--;
return NULL;
return rc;
}
/* Check whether we are still listening on our own socket. In case
another gpg-agent process started after us has taken ownership of
our socket, we would linger around without any real task. Thus we
better check once in a while whether we are really needed. */
static void
check_own_socket (void)
/* The thread running the actual check. */
static void *
check_own_socket_thread (void *arg)
{
char *sockname;
npth_t thread;
npth_attr_t tattr;
int err;
if (disable_check_own_socket)
return;
if (check_own_socket_running || shutdown_pending)
return; /* Still running or already shutting down. */
(void)arg;
sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
if (!sockname)
return; /* Out of memory. */
return NULL; /* Out of memory. */
err = npth_attr_init (&tattr);
if (err)
while (!problem_detected)
{
xfree (sockname);
return;
if (shutdown_pending)
goto leave;
gnupg_sleep (CHECK_OWN_SOCKET_INTERVAL);
if (do_check_own_socket (sockname))
problem_detected |= AGENT_PROBLEM_SOCKET_TAKEOVER;
}
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
err = npth_create (&thread, &tattr, check_own_socket_thread, sockname);
if (err)
log_error ("error spawning check_own_socket_thread: %s\n", strerror (err));
npth_attr_destroy (&tattr);
agent_kick_the_loop ();
leave:
xfree (sockname);
return NULL;
}
#endif
/* The thread running other checks. */
static void *
check_others_thread (void *arg)
{
const char *homedir = gnupg_homedir ();
(void)arg;
while (!problem_detected)
{
struct stat statbuf;
if (shutdown_pending)
goto leave;
gnupg_sleep (CHECK_PROBLEMS_INTERVAL);
/* If we are running as a child of another process, check whether
the parent is still alive and shutdown if not. */
#ifndef HAVE_W32_SYSTEM
if (parent_pid != (pid_t)(-1) && kill (parent_pid, 0))
problem_detected |= AGENT_PROBLEM_PARENT_HAS_GONE;
#endif /*HAVE_W32_SYSTEM*/
/* Check whether the homedir is still available. */
if (!have_homedir_inotify
&& gnupg_stat (homedir, &statbuf) && errno == ENOENT)
problem_detected |= AGENT_PROBLEM_HOMEDIR_REMOVED;
}
agent_kick_the_loop ();
leave:
return NULL;
}
/* Figure out whether an agent is available and running. Prints an
error if not. If SILENT is true, no messages are printed.

View File

@ -27,8 +27,83 @@
#include <sys/stat.h>
#include "agent.h"
#include "../common/openpgpdefs.h"
/* Table with parameters for KEM decryption. Use get_ecc_parms to
* find an entry. */
struct ecc_params
{
const char *curve; /* Canonical name of the curve. */
size_t pubkey_len; /* Pubkey in the SEXP representation. */
size_t scalar_len;
size_t point_len;
size_t shared_len;
int hash_algo;
int kem_algo;
int scalar_reverse;
};
static const struct ecc_params ecc_table[] =
{
{
"Curve25519",
33, 32, 32, 32,
GCRY_MD_SHA3_256, GCRY_KEM_RAW_X25519,
1
},
{
"X448",
56, 56, 56, 64,
GCRY_MD_SHA3_512, GCRY_KEM_RAW_X448,
0
},
{
"brainpoolP256r1",
65, 32, 65, 32,
GCRY_MD_SHA3_256, GCRY_KEM_RAW_BP256,
0
},
{
"brainpoolP384r1",
97, 48, 97, 64,
GCRY_MD_SHA3_512, GCRY_KEM_RAW_BP384,
0
},
{
"brainpoolP512r1",
129, 64, 129, 64,
GCRY_MD_SHA3_512, GCRY_KEM_RAW_BP512,
0
},
{ NULL, 0, 0, 0, 0, 0, 0, 0 }
};
/* Maximum buffer sizes required for ECC KEM. Keep this aligned to
* the ecc_table above. */
#define ECC_SCALAR_LEN_MAX 64
#define ECC_POINT_LEN_MAX (1+2*64)
#define ECC_HASH_LEN_MAX 64
/* Return the ECC parameters for CURVE. CURVE is expected to be the
* canonical name. */
static const struct ecc_params *
get_ecc_params (const char *curve)
{
int i;
for (i = 0; ecc_table[i].curve; i++)
if (!strcmp (ecc_table[i].curve, curve))
return &ecc_table[i];
return NULL;
}
/* DECRYPT the stuff in ciphertext which is expected to be a S-Exp.
Try to get the key from CTRL and write the decoded stuff back to
OUTFP. The padding information is stored at R_PADDING with -1
@ -41,7 +116,6 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
gcry_sexp_t s_skey = NULL, s_cipher = NULL, s_plain = NULL;
unsigned char *shadow_info = NULL;
gpg_error_t err = 0;
int no_shadow_info = 0;
char *buf = NULL;
size_t len;
@ -70,17 +144,13 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
err = agent_key_from_file (ctrl, NULL, desc_text,
NULL, &shadow_info,
CACHE_MODE_NORMAL, NULL, &s_skey, NULL, NULL);
if (gpg_err_code (err) == GPG_ERR_NO_SECKEY)
no_shadow_info = 1;
else if (err)
if (err && gpg_err_code (err) != GPG_ERR_NO_SECKEY)
{
log_error ("failed to read the secret key\n");
goto leave;
}
if (shadow_info || no_shadow_info)
else if (shadow_info
|| err /* gpg_err_code (err) == GPG_ERR_NO_SECKEY */)
{ /* divert operation to the smartcard */
if (!gcry_sexp_canon_len (ciphertext, ciphertextlen, NULL, NULL))
{
err = gpg_error (GPG_ERR_INV_SEXP);
@ -95,12 +165,12 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
&buf, &len, r_padding);
if (err)
{
/* We restore the original error (ie. no seckey) is no card
/* We restore the original error (ie. no seckey) as no card
* has been found and we have no shadow key. This avoids a
* surprising "card removed" error code. */
if ((gpg_err_code (err) == GPG_ERR_CARD_REMOVED
|| gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
&& no_shadow_info)
&& !shadow_info)
err = gpg_error (GPG_ERR_NO_SECKEY);
else
log_error ("smartcard decryption failed: %s\n", gpg_strerror (err));
@ -157,3 +227,597 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
xfree (shadow_info);
return err;
}
/* Reverse BUFFER to change the endianness. */
static void
reverse_buffer (unsigned char *buffer, unsigned int length)
{
unsigned int tmp, i;
for (i=0; i < length/2; i++)
{
tmp = buffer[i];
buffer[i] = buffer[length-1-i];
buffer[length-1-i] = tmp;
}
}
static gpg_error_t
ecc_extract_pk_from_key (const struct ecc_params *ecc, gcry_sexp_t s_skey,
unsigned char *ecc_pk)
{
gpg_error_t err;
unsigned int nbits;
const unsigned char *p;
size_t len;
gcry_mpi_t ecc_pk_mpi = NULL;
err = gcry_sexp_extract_param (s_skey, NULL, "/q", &ecc_pk_mpi, NULL);
if (err)
{
if (opt.verbose)
log_info ("%s: extracting q and d from ECC key failed\n", __func__);
return err;
}
p = gcry_mpi_get_opaque (ecc_pk_mpi, &nbits);
len = (nbits+7)/8;
if (len != ecc->pubkey_len)
{
if (opt.verbose)
log_info ("%s: ECC public key length invalid (%zu)\n", __func__, len);
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
else if (len == ecc->point_len)
memcpy (ecc_pk, p, ecc->point_len);
else if (len == ecc->point_len + 1 && p[0] == 0x40)
/* Remove the 0x40 prefix (for Curve25519) */
memcpy (ecc_pk, p+1, ecc->point_len);
else
{
err = gpg_error (GPG_ERR_BAD_SECKEY);
goto leave;
}
if (DBG_CRYPTO)
log_printhex (ecc_pk, ecc->pubkey_len, "ECC pubkey:");
leave:
mpi_release (ecc_pk_mpi);
return err;
}
static gpg_error_t
ecc_extract_sk_from_key (const struct ecc_params *ecc, gcry_sexp_t s_skey,
unsigned char *ecc_sk)
{
gpg_error_t err;
unsigned int nbits;
const unsigned char *p;
size_t len;
gcry_mpi_t ecc_sk_mpi = NULL;
err = gcry_sexp_extract_param (s_skey, NULL, "/d", &ecc_sk_mpi, NULL);
if (err)
{
if (opt.verbose)
log_info ("%s: extracting d from ECC key failed\n", __func__);
return err;
}
p = gcry_mpi_get_opaque (ecc_sk_mpi, &nbits);
len = (nbits+7)/8;
if (len > ecc->scalar_len)
{
if (opt.verbose)
log_info ("%s: ECC secret key too long (%zu)\n", __func__, len);
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
memset (ecc_sk, 0, ecc->scalar_len - len);
memcpy (ecc_sk + ecc->scalar_len - len, p, len);
if (ecc->scalar_reverse)
reverse_buffer (ecc_sk, ecc->scalar_len);
mpi_release (ecc_sk_mpi);
ecc_sk_mpi = NULL;
if (DBG_CRYPTO)
log_printhex (ecc_sk, ecc->scalar_len, "ECC seckey:");
leave:
mpi_release (ecc_sk_mpi);
return err;
}
static gpg_error_t
ecc_raw_kem (const struct ecc_params *ecc, gcry_sexp_t s_skey,
const unsigned char *ecc_ct, unsigned char *ecc_ecdh)
{
gpg_error_t err = 0;
unsigned char ecc_sk[ECC_SCALAR_LEN_MAX];
if (ecc->scalar_len > ECC_SCALAR_LEN_MAX)
{
if (opt.verbose)
log_info ("%s: ECC scalar length invalid (%zu)\n",
__func__, ecc->scalar_len);
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
err = ecc_extract_sk_from_key (ecc, s_skey, ecc_sk);
if (err)
goto leave;
err = gcry_kem_decap (ecc->kem_algo, ecc_sk, ecc->scalar_len,
ecc_ct, ecc->point_len, ecc_ecdh, ecc->point_len,
NULL, 0);
if (err)
{
if (opt.verbose)
log_info ("%s: gcry_kem_decap for ECC failed\n", __func__);
}
leave:
wipememory (ecc_sk, sizeof ecc_sk);
return err;
}
static gpg_error_t
get_cardkey (ctrl_t ctrl, const char *keygrip, gcry_sexp_t *r_s_pk)
{
gpg_error_t err;
unsigned char *pkbuf;
size_t pkbuflen;
err = agent_card_readkey (ctrl, keygrip, &pkbuf, NULL);
if (err)
return err;
pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
err = gcry_sexp_sscan (r_s_pk, NULL, (char*)pkbuf, pkbuflen);
if (err)
log_error ("failed to build S-Exp from received card key: %s\n",
gpg_strerror (err));
xfree (pkbuf);
return err;
}
static gpg_error_t
ecc_get_curve (ctrl_t ctrl, gcry_sexp_t s_skey, const char **r_curve)
{
gpg_error_t err = 0;
gcry_sexp_t s_skey_card = NULL;
const char *curve = NULL;
gcry_sexp_t key;
*r_curve = NULL;
if (!s_skey)
{
err = get_cardkey (ctrl, ctrl->keygrip, &s_skey_card);
if (err)
goto leave;
key = s_skey_card;
}
else
key = s_skey;
curve = get_ecc_curve_from_key (key);
if (!curve)
{
err = gpg_error (GPG_ERR_BAD_SECKEY);
goto leave;
}
*r_curve = curve;
leave:
gcry_sexp_release (s_skey_card);
return err;
}
/* Given a private key in SEXP by S_SKEY0 and a cipher text by ECC_CT
* with length ECC_POINT_LEN, do ECC-KEM operation. Result is
* returned in the memory referred by ECC_SS. Shared secret length is
* returned in the memory referred by R_SHARED_LEN. CTRL is used to
* access smartcard, internally. */
static gpg_error_t
ecc_pgp_kem_decrypt (ctrl_t ctrl, gcry_sexp_t s_skey0,
unsigned char *shadow_info0,
const unsigned char *ecc_ct, size_t ecc_point_len,
unsigned char *ecc_ss, size_t *r_shared_len)
{
gpg_error_t err;
unsigned char ecc_ecdh[ECC_POINT_LEN_MAX];
unsigned char ecc_pk[ECC_POINT_LEN_MAX];
const char *curve;
const struct ecc_params *ecc = NULL;
if (ecc_point_len > ECC_POINT_LEN_MAX)
return gpg_error (GPG_ERR_INV_DATA);
err = ecc_get_curve (ctrl, s_skey0, &curve);
if (err)
{
if ((gpg_err_code (err) == GPG_ERR_CARD_REMOVED
|| gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
&& !s_skey0)
err = gpg_error (GPG_ERR_NO_SECKEY);
return err;
}
ecc = get_ecc_params (curve);
if (!ecc)
{
if (opt.verbose)
log_info ("%s: curve '%s' not supported\n", __func__, curve);
return gpg_error (GPG_ERR_BAD_SECKEY);
}
*r_shared_len = ecc->shared_len;
if (DBG_CRYPTO)
log_debug ("ECC curve: %s\n", curve);
if (ecc->point_len != ecc_point_len)
{
if (opt.verbose)
log_info ("%s: ECC cipher text length invalid (%zu != %zu)\n",
__func__, ecc->point_len, ecc_point_len);
return gpg_error (GPG_ERR_INV_DATA);
}
err = ecc_extract_pk_from_key (ecc, s_skey0, ecc_pk);
if (err)
return err;
if (DBG_CRYPTO)
log_printhex (ecc_ct, ecc->point_len, "ECC ephem:");
if (shadow_info0 || !s_skey0)
{
if (s_skey0 && agent_is_tpm2_key (s_skey0))
{
log_error ("TPM decryption failed: %s\n", gpg_strerror (err));
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
else
{
err = agent_card_ecc_kem (ctrl, ecc_ct, ecc->point_len, ecc_ecdh);
if (err)
{
log_error ("smartcard decryption failed: %s\n",
gpg_strerror (err));
return err;
}
}
}
else
err = ecc_raw_kem (ecc, s_skey0, ecc_ct, ecc_ecdh);
if (err)
return err;
if (DBG_CRYPTO)
log_printhex (ecc_ecdh, ecc_point_len, "ECC ecdh:");
err = gnupg_ecc_kem_kdf (ecc_ss, ecc->shared_len, ecc->hash_algo,
ecc_ecdh, ecc->point_len, ecc_ct, ecc->point_len,
ecc_pk, ecc->point_len);
wipememory (ecc_ecdh, sizeof ecc_ecdh);
if (err)
{
if (opt.verbose)
log_info ("%s: kdf for ECC failed\n", __func__);
return err;
}
if (DBG_CRYPTO)
log_printhex (ecc_ss, ecc->shared_len, "ECC shared:");
return 0;
}
/* For composite PGP KEM (ECC+ML-KEM), decrypt CIPHERTEXT using KEM API.
First keygrip is for ECC, second keygrip is for PQC. CIPHERTEXT
should follow the format of:
(enc-val(pqc(c%d)(e%m)(k%m)(s%m)(fixed-info&)))
c: cipher identifier (symmetric)
e: ECDH ciphertext
k: ML-KEM ciphertext
s: encrypted session key
fixed-info: A buffer with the fixed info.
FIXME: For now, possible keys on smartcard are not supported.
*/
static gpg_error_t
composite_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
gcry_sexp_t s_cipher, membuf_t *outbuf)
{
gcry_sexp_t s_skey0 = NULL;
gcry_sexp_t s_skey1 = NULL;
unsigned char *shadow_info0 = NULL;
unsigned char *shadow_info1 = NULL;
gpg_error_t err = 0;
unsigned int nbits;
size_t len;
int algo;
gcry_mpi_t encrypted_sessionkey_mpi = NULL;
const unsigned char *encrypted_sessionkey;
size_t encrypted_sessionkey_len;
gcry_mpi_t ecc_ct_mpi = NULL;
const unsigned char *ecc_ct;
size_t ecc_ct_len;
unsigned char ecc_ss[ECC_HASH_LEN_MAX];
size_t ecc_shared_len, ecc_point_len;
enum gcry_kem_algos mlkem_kem_algo;
gcry_mpi_t mlkem_sk_mpi = NULL;
gcry_mpi_t mlkem_ct_mpi = NULL;
const unsigned char *mlkem_sk;
size_t mlkem_sk_len;
const unsigned char *mlkem_ct;
size_t mlkem_ct_len;
unsigned char mlkem_ss[GCRY_KEM_MLKEM1024_SHARED_LEN];
size_t mlkem_ss_len;
unsigned char kek[32];
size_t kek_len = 32; /* AES-256 is mandatory */
gcry_cipher_hd_t hd;
unsigned char sessionkey[256];
size_t sessionkey_len;
gcry_buffer_t fixed_info = { 0, 0, 0, NULL };
err = agent_key_from_file (ctrl, NULL, desc_text,
ctrl->keygrip, &shadow_info0,
CACHE_MODE_NORMAL, NULL, &s_skey0, NULL, NULL);
if (err && gpg_err_code (err) != GPG_ERR_NO_SECKEY)
{
log_error ("failed to read the secret key\n");
goto leave;
}
err = agent_key_from_file (ctrl, NULL, desc_text,
ctrl->keygrip1, &shadow_info1,
CACHE_MODE_NORMAL, NULL, &s_skey1, NULL, NULL);
/* Here assumes no smartcard for ML-KEM, but private key in a file. */
if (err)
{
log_error ("failed to read the another secret key\n");
goto leave;
}
err = gcry_sexp_extract_param (s_cipher, NULL, "%dc/eks&'fixed-info'",
&algo, &ecc_ct_mpi, &mlkem_ct_mpi,
&encrypted_sessionkey_mpi, &fixed_info, NULL);
if (err)
{
if (opt.verbose)
log_info ("%s: extracting parameters failed\n", __func__);
goto leave;
}
ecc_ct = gcry_mpi_get_opaque (ecc_ct_mpi, &nbits);
ecc_ct_len = (nbits+7)/8;
len = gcry_cipher_get_algo_keylen (algo);
encrypted_sessionkey = gcry_mpi_get_opaque (encrypted_sessionkey_mpi, &nbits);
encrypted_sessionkey_len = (nbits+7)/8;
if (len == 0 || encrypted_sessionkey_len != len + 8)
{
if (opt.verbose)
log_info ("%s: encrypted session key length %zu"
" does not match the length for algo %d\n",
__func__, encrypted_sessionkey_len, algo);
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
/* Firstly, ECC part. */
ecc_point_len = ecc_ct_len;
err = ecc_pgp_kem_decrypt (ctrl, s_skey0, shadow_info0, ecc_ct, ecc_point_len,
ecc_ss, &ecc_shared_len);
if (err)
goto leave;
/* Secondly, PQC part. For now, we assume ML-KEM. */
err = gcry_sexp_extract_param (s_skey1, NULL, "/s", &mlkem_sk_mpi, NULL);
if (err)
{
if (opt.verbose)
log_info ("%s: extracting s from PQ key failed\n", __func__);
goto leave;
}
mlkem_sk = gcry_mpi_get_opaque (mlkem_sk_mpi, &nbits);
mlkem_sk_len = (nbits+7)/8;
if (mlkem_sk_len == GCRY_KEM_MLKEM512_SECKEY_LEN)
{
mlkem_kem_algo = GCRY_KEM_MLKEM512;
mlkem_ss_len = GCRY_KEM_MLKEM512_SHARED_LEN;
mlkem_ct_len = GCRY_KEM_MLKEM512_CIPHER_LEN;
}
else if (mlkem_sk_len == GCRY_KEM_MLKEM768_SECKEY_LEN)
{
mlkem_kem_algo = GCRY_KEM_MLKEM768;
mlkem_ss_len = GCRY_KEM_MLKEM768_SHARED_LEN;
mlkem_ct_len = GCRY_KEM_MLKEM768_CIPHER_LEN;
}
else if (mlkem_sk_len == GCRY_KEM_MLKEM1024_SECKEY_LEN)
{
mlkem_kem_algo = GCRY_KEM_MLKEM1024;
mlkem_ss_len = GCRY_KEM_MLKEM1024_SHARED_LEN;
mlkem_ct_len = GCRY_KEM_MLKEM1024_CIPHER_LEN;
}
else
{
if (opt.verbose)
log_info ("%s: PQ key length invalid (%zu)\n", __func__, mlkem_sk_len);
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
mlkem_ct = gcry_mpi_get_opaque (mlkem_ct_mpi, &nbits);
len = (nbits+7)/8;
if (len != mlkem_ct_len)
{
if (opt.verbose)
log_info ("%s: PQ cipher text length invalid (%zu)\n",
__func__, mlkem_ct_len);
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
err = gcry_kem_decap (mlkem_kem_algo, mlkem_sk, mlkem_sk_len,
mlkem_ct, mlkem_ct_len, mlkem_ss, mlkem_ss_len,
NULL, 0);
if (err)
{
if (opt.verbose)
log_info ("%s: gcry_kem_decap for PQ failed\n", __func__);
goto leave;
}
mpi_release (mlkem_sk_mpi);
mlkem_sk_mpi = NULL;
/* Then, combine two shared secrets and ciphertexts into one KEK */
err = gnupg_kem_combiner (kek, kek_len,
ecc_ss, ecc_shared_len, ecc_ct, ecc_point_len,
mlkem_ss, mlkem_ss_len, mlkem_ct, mlkem_ct_len,
fixed_info.data, fixed_info.size);
if (err)
{
if (opt.verbose)
log_info ("%s: KEM combiner failed\n", __func__);
goto leave;
}
mpi_release (ecc_ct_mpi);
ecc_ct_mpi = NULL;
mpi_release (mlkem_ct_mpi);
mlkem_ct_mpi = NULL;
if (DBG_CRYPTO)
{
log_printhex (kek, kek_len, "KEK key: ");
}
err = gcry_cipher_open (&hd, GCRY_CIPHER_AES256,
GCRY_CIPHER_MODE_AESWRAP, 0);
if (err)
{
if (opt.verbose)
log_error ("ecdh failed to initialize AESWRAP: %s\n",
gpg_strerror (err));
goto leave;
}
err = gcry_cipher_setkey (hd, kek, kek_len);
sessionkey_len = encrypted_sessionkey_len - 8;
err = gcry_cipher_decrypt (hd, sessionkey, sessionkey_len,
encrypted_sessionkey, encrypted_sessionkey_len);
gcry_cipher_close (hd);
mpi_release (encrypted_sessionkey_mpi);
encrypted_sessionkey_mpi = NULL;
if (err)
{
log_error ("KEM decrypt failed: %s\n", gpg_strerror (err));
goto leave;
}
put_membuf_printf (outbuf,
"(5:value%u:", (unsigned int)sessionkey_len);
put_membuf (outbuf, sessionkey, sessionkey_len);
put_membuf (outbuf, ")", 2);
leave:
wipememory (ecc_ss, sizeof ecc_ss);
wipememory (mlkem_ss, sizeof mlkem_ss);
wipememory (kek, sizeof kek);
wipememory (sessionkey, sizeof sessionkey);
mpi_release (ecc_ct_mpi);
mpi_release (mlkem_sk_mpi);
mpi_release (mlkem_ct_mpi);
mpi_release (encrypted_sessionkey_mpi);
gcry_free (fixed_info.data);
gcry_sexp_release (s_skey0);
gcry_sexp_release (s_skey1);
xfree (shadow_info0);
xfree (shadow_info1);
return err;
}
/* DECRYPT the encrypted stuff (like encrypted session key) in
CIPHERTEXT using KEM API, with KEMID. Keys (or a key) are
specified in CTRL. DESC_TEXT is used to retrieve private key.
OPTION can be specified for upper layer option for KEM. Decrypted
stuff (like session key) is written to OUTBUF.
*/
gpg_error_t
agent_kem_decrypt (ctrl_t ctrl, const char *desc_text, int kemid,
const unsigned char *ciphertext, size_t ciphertextlen,
const unsigned char *option, size_t optionlen,
membuf_t *outbuf)
{
gcry_sexp_t s_cipher = NULL;
gpg_error_t err = 0;
/* For now, only PQC-PGP is supported. */
if (kemid != KEM_PQC_PGP)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
(void)optionlen;
if (kemid == KEM_PQC_PGP && option)
{
log_error ("PQC-PGP requires no option\n");
return gpg_error (GPG_ERR_INV_ARG);
}
if (!ctrl->have_keygrip)
{
log_error ("speculative decryption not yet supported\n");
return gpg_error (GPG_ERR_NO_SECKEY);
}
if (!ctrl->have_keygrip1)
{
log_error ("Composite KEM requires two KEYGRIPs\n");
return gpg_error (GPG_ERR_NO_SECKEY);
}
err = gcry_sexp_sscan (&s_cipher, NULL, (char*)ciphertext, ciphertextlen);
if (err)
{
log_error ("failed to convert ciphertext: %s\n", gpg_strerror (err));
return gpg_error (GPG_ERR_INV_DATA);
}
if (DBG_CRYPTO)
{
log_printhex (ctrl->keygrip, 20, "keygrip0:");
log_printhex (ctrl->keygrip1, 20, "keygrip1:");
gcry_log_debugsxp ("cipher", s_cipher);
}
err = composite_pgp_kem_decrypt (ctrl, desc_text, s_cipher, outbuf);
gcry_sexp_release (s_cipher);
return err;
}

View File

@ -38,14 +38,14 @@ struct trustitem_s
{
struct
{
int disabled:1; /* This entry is disabled. */
int for_pgp:1; /* Set by '*' or 'P' as first flag. */
int for_smime:1; /* Set by '*' or 'S' as first flag. */
int relax:1; /* Relax checking of root certificate
unsigned int disabled:1; /* This entry is disabled. */
unsigned int for_pgp:1; /* Set by '*' or 'P' as first flag. */
unsigned int for_smime:1; /* Set by '*' or 'S' as first flag. */
unsigned int relax:1; /* Relax checking of root certificate
constraints. */
int cm:1; /* Use chain model for validation. */
int qual:1; /* Root CA for qualified signatures. */
int de_vs:1; /* Root CA for de-vs compliant PKI. */
unsigned int cm:1; /* Use chain model for validation. */
unsigned int qual:1; /* Root CA for qualified signatures. */
unsigned int de_vs:1; /* Root CA for de-vs compliant PKI. */
} flags;
unsigned char fpr[20]; /* The binary fingerprint. */
};

View File

@ -28,15 +28,24 @@ cvtver () {
usage()
{
cat <<EOF
Usage: $(basename $0) [OPTIONS]
Usage: $(basename $0) [OPTIONS] [packages]
Get the online version of the GnuPG software version database
and optionally download packages and verify their signatures.
Options:
--info Print only infos about packages
--skip-download Assume download has already been done.
--skip-verify Do not check signatures
--skip-selfcheck Do not check GnuPG version
(default if not used in the GnuPG tree)
--find-sha1sum Print the name of the sha1sum utility
--find-sha256sum Print the name of the sha256sum utility
--help Print this help.
Example:
getswdb.sh gnupg24 gpgme libksba libassuan
EOF
exit $1
}
@ -49,6 +58,9 @@ skip_verify=no
skip_selfcheck=no
find_sha1sum=no
find_sha256sum=no
info_mode=no
packages=
die=no
while test $# -gt 0; do
case "$1" in
# Set up `optarg'.
@ -79,13 +91,20 @@ while test $# -gt 0; do
--find-sha256sum)
find_sha256sum=yes
;;
*)
--info)
info_mode=yes
;;
--*)
usage 1 1>&2
;;
*)
packages="$packages $1"
;;
esac
shift
done
# Mac OSX has only a shasum and not sha1sum
if [ ${find_sha1sum} = yes ]; then
for i in sha1sum shasum ; do
@ -114,16 +133,37 @@ if [ ${find_sha256sum} = yes ]; then
fi
if [ $skip_verify = no ]; then
if [ ! -f "$distsigkey" ]; then
distsigkey="/usr/local/share/gnupg/distsigkey.gpg"
if [ ! -f "$distsigkey" ]; then
distsigkey="/usr/share/gnupg/distsigkey.gpg"
if [ ! -f "$distsigkey" ]; then
echo "no keyring with release keys found!" >&2
exit 1
fi
fi
echo "using release keys from $distsigkey" >&2
skip_selfcheck=yes
fi
fi
# Get GnuPG version from VERSION file. For a GIT checkout this means
# that ./autogen.sh must have been run first. For a regular tarball
# VERSION is always available.
if [ ! -f "$srcdir/../VERSION" ]; then
if [ $skip_selfcheck = no ]; then
if [ ! -f "$srcdir/../VERSION" ]; then
echo "VERSION file missing - run autogen.sh first." >&2
exit 1
fi
version=$(cat "$srcdir/../VERSION")
else
version="0.0.0"
fi
version=$(cat "$srcdir/../VERSION")
version_num=$(echo "$version" | cvtver)
if [ $skip_verify = no ]; then
if ! $GPGV --version >/dev/null 2>/dev/null ; then
echo "command \"gpgv\" is not installed" >&2
@ -164,10 +204,10 @@ else
fi
fi
if [ $skip_verify = no ]; then
if ! $GPGV --keyring "$distsigkey" swdb.lst.sig swdb.lst; then
if ! $GPGV --keyring "$distsigkey" swdb.lst.sig swdb.lst 2>/dev/null; then
echo "list of software versions is not valid!" >&2
exit 1
fi
fi
fi
#
@ -188,3 +228,73 @@ if [ $skip_selfcheck = no ]; then
exit 1
fi
fi
# Download a package and check its signature.
download_pkg () {
local url="$1"
local file="${url##*/}"
if ! $WGET -q -O - "$url" >"${file}.tmp" ; then
echo "download of $file failed." >&2
[ -f "${file}.tmp" ] && rm "${file}.tmp"
return 1
fi
if [ $skip_verify = no ]; then
if ! $WGET -q -O - "${url}.sig" >"${file}.tmpsig" ; then
echo "download of $file.sig failed." >&2
[ -f "${file}.tmpsig" ] && rm "${file}.tmpsig"
return 1
fi
if ! $GPGV -q --keyring "$distsigkey" \
"${file}.tmpsig" "${file}.tmp" 2>/dev/null; then
echo "signature of $file is not valid!" >&2
return 1
fi
mv "${file}.tmpsig" "${file}.sig"
else
[ -f "${file}.sig" ] && rm "${file}.sig"
fi
mv "${file}.tmp" "${file}"
return 0
}
baseurl=$(awk '$1=="gpgorg_base" {print $2; exit 0}' swdb.lst)
for p in $packages; do
pver=$(awk '$1=="'"$p"'_ver" {print $2}' swdb.lst)
if [ -z "$pver" ]; then
echo "package '$p' not found" >&2
die=yes
else
pdir=$(awk '$1=="'"$p"'_dir" {print $2":"$3":"$4}' swdb.lst)
if [ -n "$pdir" ]; then
psuf=$(echo "$pdir" | cut -d: -f3)
pname=$(echo "$pdir" | cut -d: -f2)
pdir=$(echo "$pdir" | cut -d: -f1)
else
psuf=
pdir="$p"
pname="$p"
fi
if [ -z "$psuf" ]; then
psuf=$(awk 'BEGIN {suf="bz2"};
$1=="'"$p"'_sha1_gz" {suf="gz"; exit 0};
$1=="'"$p"'_sha1_xz" {suf"xz"; exit 0};
END {print suf}' swdb.lst)
fi
pfullname="$pname-$pver.tar.$psuf"
if [ $info_mode = yes ]; then
echo "$baseurl/$pdir/$pfullname"
else
echo "downloading $pfullname"
download_pkg "$baseurl/$pdir/$pfullname" || die=yes
fi
fi
done
if [ $die = yes ]; then
echo "errors found!" >&2
exit 1
fi
exit 0

View File

@ -43,52 +43,7 @@
#
# The information required to sign the tarballs and binaries
# are expected in the developer specific file ~/.gnupg-autogen.rc".
# Here is an example:
#--8<---------------cut here---------------start------------->8---
# # Location of the released tarball archives. Note that this is an
# # internal archive and before uploading this to the public server,
# # manual tests should be run and the git release tagged and pushed.
# # This is greped by the Makefile.
# RELEASE_ARCHIVE=foo@somehost:tarball-archive
#
# # The key used to sign the released sources.
# # This is greped by the Makefile.
# RELEASE_SIGNKEY=6DAA6E64A76D2840571B4902528897B826403ADA
#
# # For signing Windows binaries we need to employ a Windows machine.
# # We connect to this machine via ssh and take the connection
# # parameters via .ssh/config. For example a VM could be specified
# # like this:
# #
# # Host authenticode-signhost
# # HostName localhost
# # Port 27042
# # User gpgsign
# #
# # Depending on the used token it might be necessary to allow single
# # signon and unlock the token before running the make. The following
# # variable references this entry. This is greped by the Makefile.
# AUTHENTICODE_SIGNHOST=authenticode-signhost
#
# # The name of the signtool as used on Windows.
# # This is greped by the Makefile.
# AUTHENTICODE_TOOL="C:\Program Files (x86)\Windows Kits\10\bin\signtool.exe"
#
# # To use osslsigncode the follwing entries are required and
# # an empty string must be given for AUTHENTICODE_SIGNHOST.
# # They are greped by the Makefile.
# AUTHENTICODE_KEY=/home/foo/.gnupg/my-authenticode-key.p12
# AUTHENTICODE_CERTS=/home/foo/.gnupg/my-authenticode-certs.pem
#
# # If a smartcard is used for the Authenticode signature these
# # entries are required instead:
# AUTHENTICODE_KEY=card
# AUTHENTICODE_CERTS=/home/foo/.gnupg/my_authenticode_cert.pem
# OSSLSIGNCODE=/usr/bin/osslsigncode
# OSSLPKCS11ENGINE=/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so
# SCUTEMODULE=/usr/local/lib/scute.so
#
#--8<---------------cut here---------------end--------------->8---
# Use "gpg-authcode-sign.sh --template" to create a template.
# We need to know our own name.
@ -118,6 +73,7 @@ help:
@echo 'Use WIXPREFIX to provide the WIX binaries for the MSI package.'
@echo ' Using WIX also requires wine with installed wine mono.'
@echo ' See help-wixlib for more information'
@echo 'Set W32VERSION=w64 to build a 64 bit Windows version.'
help-wixlib:
@echo 'The buildsystem can create a wixlib to build MSI packages.'
@ -202,9 +158,12 @@ w32-release-offline: check-tools
# to "this" from the unpacked sources.
WHAT=git
# Set target to "native" or "w32"
# Set target to "native" or "w32".
TARGETOS=
# To build a 64 bit Windows version also change this to "w64"
W32VERSION=w32
# Set to 1 to use a pre-installed swdb.lst instead of the online version.
CUSTOM_SWDB=0
@ -225,6 +184,8 @@ TARBALLS=$(shell pwd)/../tarballs
MAKE_J=6
# Name to use for the w32 installer and sources
INST_NAME=gnupg-w32
# Use this to override the installaion directory for native builds.
@ -238,15 +199,8 @@ PATCHELF := $(shell patchelf --version 2>/dev/null >/dev/null || echo "echo plea
# Read signing information from ~/.gnupg-autogen.rc
define READ_AUTOGEN_template
$(1) = $$(shell grep '^$(1)=' $$$$HOME/.gnupg-autogen.rc|cut -d= -f2)
$(1) = $$(shell grep '^[[:blank:]]*$(1)[[:blank:]]*=' $$$$HOME/.gnupg-autogen.rc|cut -d= -f2|xargs)
endef
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_SIGNHOST))
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_TOOL))
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_KEY))
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_CERTS))
$(eval $(call READ_AUTOGEN_template,OSSLSIGNCODE))
$(eval $(call READ_AUTOGEN_template,OSSLPKCS11ENGINE))
$(eval $(call READ_AUTOGEN_template,SCUTEMODULE))
$(eval $(call READ_AUTOGEN_template,OVERRIDE_TARBALLS))
@ -323,7 +277,12 @@ endif
# Packages which are additionally build for 64 bit Windows. They are
# only used for gpgex and thus we need to build them only if we want
# a full installer.
speedo_w64_spkgs =
ifeq ($(W32VERSION),w64)
# Keep this empty
speedo_w64_spkgs =
else
speedo_w64_spkgs =
endif
# Packages which use the gnupg autogen.sh build style
speedo_gnupg_style = \
@ -355,7 +314,7 @@ endif
# Version numbers of the released packages
gnupg_ver_this = $(shell cat $(topsrc)/VERSION)
gnupg_ver := $(shell awk '$$1=="gnupg24_ver" {print $$2}' swdb.lst)
gnupg_ver := $(shell awk '$$1=="gnupg26_ver" {print $$2}' swdb.lst)
libgpg_error_ver := $(shell awk '$$1=="libgpg_error_ver" {print $$2}' swdb.lst)
libgpg_error_sha1:= $(shell awk '$$1=="libgpg_error_sha1" {print $$2}' swdb.lst)
@ -402,7 +361,7 @@ sqlite_sha1 := $(shell awk '$$1=="sqlite_sha1_gz" {print $$2}' swdb.lst)
sqlite_sha2 := $(shell awk '$$1=="sqlite_sha2_gz" {print $$2}' swdb.lst)
$(info Information from the version database)
$(info Information from the version database:)
$(info GnuPG ..........: $(gnupg_ver) (building $(gnupg_ver_this)))
$(info GpgRT ..........: $(libgpg_error_ver))
$(info Npth ...........: $(npth_ver))
@ -417,6 +376,21 @@ $(info GPGME ..........: $(gpgme_ver))
$(info Pinentry .......: $(pinentry_ver))
endif
$(info Information for this run:)
$(info Build type .....: $(WHAT))
$(info Target .........: $(TARGETOS))
ifeq ($(TARGETOS),w32)
ifeq ($(W32VERSION),w64)
$(info Windows version : 64 bit)
else
$(info Windows version : 32 bit)
ifneq ($(W32VERSION),w32)
$(error W32VERSION is not set to a proper value: Use only w32 or w64)
endif
endif
endif
# Version number for external packages
pkg_config_ver = 0.23
libiconv_ver = 1.14
@ -507,8 +481,8 @@ speedo_pkg_gettext_tar = $(pkg2rep)/gettext-$(gettext_ver).tar.gz
speedo_pkg_npth_configure = --enable-static
speedo_pkg_libgpg_error_configure = --enable-static --enable-install-gpg-error-config
speedo_pkg_w64_libgpg_error_configure = --enable-static --enable-install-gpg-error-config
speedo_pkg_libgpg_error_configure = --enable-static
speedo_pkg_w64_libgpg_error_configure = --enable-static
speedo_pkg_libassuan_configure = --enable-static
speedo_pkg_w64_libassuan_configure = --enable-static
@ -644,12 +618,21 @@ report: report-speedo
clean: clean-speedo
ifeq ($(W32VERSION),w64)
W32CC_PREFIX = x86_64
else
W32CC_PREFIX = i686
endif
ifeq ($(TARGETOS),w32)
STRIP = i686-w64-mingw32-strip
STRIP = $(W32CC_PREFIX)-w64-mingw32-strip
W32STRIP32 = i686-w64-mingw32-strip
else
STRIP = strip
endif
W32CC = i686-w64-mingw32-gcc
W32CC = $(W32CC_PREFIX)-w64-mingw32-gcc
W32CC32 = i686-w64-mingw32-gcc
-include config.mk
@ -691,9 +674,9 @@ ifneq ($(TARGETOS),)
# Determine build and host system
build := $(shell $(topsrc)/autogen.sh --silent --print-build)
ifeq ($(TARGETOS),w32)
speedo_autogen_buildopt := --build-w32
speedo_autogen_buildopt := --build-$(W32VERSION)
speedo_autogen_buildopt6 := --build-w64
host := $(shell $(topsrc)/autogen.sh --silent --print-host --build-w32)
host := $(shell $(topsrc)/autogen.sh --silent --print-host --build-$(W32VERSION))
host6:= $(shell $(topsrc)/autogen.sh --silent --print-host --build-w64)
speedo_host_build_option := --host=$(host) --build=$(build)
speedo_host_build_option6 := --host=$(host6) --build=$(build)
@ -917,7 +900,7 @@ else ifneq ($(findstring $(1),$(speedo_gnupg_style)),)
mkdir "$$$${pkgbdir}"; \
cd "$$$${pkgbdir}"; \
if [ -n "$(speedo_autogen_buildopt)" ]; then \
eval AUTOGEN_SH_SILENT=1 w32root="$(idir)" \
eval AUTOGEN_SH_SILENT=1 $(W32VERSION)root="$(idir)" \
"$$$${pkgsdir}/autogen.sh" \
$(speedo_autogen_buildopt) \
$$$${pkgcfg} $$$${pkgextracflags}; \
@ -1126,8 +1109,8 @@ ifneq ($(TARGETOS),w32)
echo "speedo: * Now copy $(idir)/ to the final location and" ;\
echo "speedo: * adjust $(idir)/bin/gpgconf.ctl accordingly" ;\
echo "speedo: * Or run:" ;\
echo "speedo: * make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg24" ;\
echo "speedo: * ldconfig -n /usr/local/gnupg24/lib";\
echo "speedo: * make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg26" ;\
echo "speedo: * ldconfig -n /usr/local/gnupg26/lib";\
echo "speedo: */")
endif
@ -1142,8 +1125,8 @@ ifneq ($(TARGETOS),w32)
echo "speedo: ERROR: SYSROOT has not been given";\
echo "speedo: Set SYSROOT to the desired install directory";\
echo "speedo: Example:";\
echo "speedo: make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg24";\
echo "speedo: ldconfig -n /usr/local/gnupg24/lib";\
echo "speedo: make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg26";\
echo "speedo: ldconfig -n /usr/local/gnupg26/lib";\
exit 1;\
fi;\
if [ ! -d "$$SYSROOT"/bin ]; then if ! mkdir "$$SYSROOT"/bin; then \
@ -1231,13 +1214,13 @@ $(bdir)/README.txt: $(bdir)/NEWS.tmp $(topsrc)/README $(w32src)/README.txt \
$(bdir)/g4wihelp.dll: $(w32src)/g4wihelp.c $(w32src)/exdll.h $(w32src)/exdll.c
(set -e; cd $(bdir); \
$(W32CC) -DUNICODE -static-libgcc -I . -O2 -c \
$(W32CC32) -DUNICODE -static-libgcc -I . -O2 -c \
-o exdll.o $(w32src)/exdll.c; \
$(W32CC) -DUNICODE -static-libgcc -I. -shared -O2 \
$(W32CC32) -DUNICODE -static-libgcc -I. -shared -O2 \
-o g4wihelp.dll $(w32src)/g4wihelp.c exdll.o \
-lwinmm -lgdi32 -luserenv \
-lshell32 -loleaut32 -lshlwapi -lmsimg32; \
$(STRIP) g4wihelp.dll)
$(W32STRIP32) g4wihelp.dll)
w32_insthelpers: $(bdir)/g4wihelp.dll
@ -1333,7 +1316,7 @@ wixlib: installer $(bdir)/README.txt $(w32src)/wixlib.wxs
)
define MKSWDB_commands
( pref="#+macro: gnupg24_w32_$(3)" ;\
( pref="#+macro: gnupg26_w32_$(3)" ;\
echo "$${pref}ver $(INST_VERSION)_$(BUILD_DATESTR)" ;\
echo "$${pref}date $(2)" ;\
echo "$${pref}size $$(wc -c <$(1)|awk '{print int($$1/1024)}')k";\
@ -1344,35 +1327,13 @@ endef
# Sign the file $1 and save the result as $2
define AUTHENTICODE_sign
set -e;\
if [ -n "$(AUTHENTICODE_SIGNHOST)" ]; then \
echo "speedo: Signing via host $(AUTHENTICODE_SIGNHOST)";\
scp $(1) "$(AUTHENTICODE_SIGNHOST):a.exe" ;\
ssh "$(AUTHENTICODE_SIGNHOST)" '$(AUTHENTICODE_TOOL)' sign \
/a /n '"g10 Code GmbH"' \
/tr 'http://rfc3161timestamp.globalsign.com/advanced' /td sha256 \
/fd sha256 /du https://gnupg.org a.exe ;\
scp "$(AUTHENTICODE_SIGNHOST):a.exe" $(2);\
echo "speedo: signed file is '$(2)'" ;\
elif [ "$(AUTHENTICODE_KEY)" = card ]; then \
echo "speedo: Signing using a card: '$(1)'";\
$(OSSLSIGNCODE) sign \
-pkcs11engine $(OSSLPKCS11ENGINE) \
-pkcs11module $(SCUTEMODULE) \
-certs $(AUTHENTICODE_CERTS) \
-h sha256 -n GnuPG -i https://gnupg.org \
-ts http://rfc3161timestamp.globalsign.com/advanced \
-in $(1) -out $(2).tmp ; mv $(2).tmp $(2) ; \
elif [ -e "$(AUTHENTICODE_KEY)" ]; then \
echo "speedo: Signing using key $(AUTHENTICODE_KEY)";\
osslsigncode sign -certs $(AUTHENTICODE_CERTS) \
-pkcs12 $(AUTHENTICODE_KEY) -askpass \
-ts "http://timestamp.globalsign.com/scripts/timstamp.dll" \
-h sha256 -n GnuPG -i https://gnupg.org \
-in $(1) -out $(2) ;\
(set -e; \
if gpg-authcode-sign.sh --version >/dev/null; then \
gpg-authcode-sign.sh "$(1)" "$(2)"; \
else \
echo "speedo: WARNING: Binaries are not signed"; \
fi
echo 2>&1 "warning: Please install gpg-authcode-sign.sh to sign files." ;\
[ "$(1)" != "$(2)" ] && cp "$(1)" "$(2)" ;\
fi)
endef
# Help target for testing to sign a file.

View File

@ -46,7 +46,7 @@ Unicode true
!define PRETTY_PACKAGE "GNU Privacy Guard"
!define PRETTY_PACKAGE_SHORT "GnuPG"
!define COMPANY "The GnuPG Project"
!define COPYRIGHT "Copyright (C) 2021 g10 Code GmbH"
!define COPYRIGHT "Copyright (C) 2024 g10 Code GmbH"
!define DESCRIPTION "GnuPG: The GNU Privacy Guard for Windows"
!define INSTALL_DIR "GnuPG"
@ -63,13 +63,13 @@ Unicode true
GnuPG includes an advanced key management facility and is compliant \
with the OpenPGP Internet standard as described in RFC-4880. \
\r\n\r\n$_CLICK \
\r\n\r\n\r\n\r\n\r\nThis is GnuPG version ${VERSION}.\r\n\
\r\n\r\n\r\n\r\n\r\nThis is GnuPG version ${VERSION} (64 bit).\r\n\
File version: ${PROD_VERSION}\r\n\
Release date: ${BUILD_ISODATE}"
!define ABOUT_GERMAN \
"GnuPG is die häufigst verwendete Software zur Mail- und Datenverschlüsselung.\
\r\n\r\n$_CLICK \
\r\n\r\n\r\n\r\n\r\nDies ist GnuPG Version ${VERSION}.\r\n\
\r\n\r\n\r\n\r\n\r\nDies ist GnuPG Version ${VERSION} (64 bit).\r\n\
Dateiversion: ${PROD_VERSION}\r\n\
Releasedatum: ${BUILD_ISODATE}"
@ -119,7 +119,7 @@ OutFile "${NAME}-${VERSION}_${BUILD_DATESTR}.exe"
!ifndef INSTALL_DIR
!define INSTALL_DIR "GnuPG"
!endif
InstallDir "$PROGRAMFILES\${INSTALL_DIR}"
InstallDir "$PROGRAMFILES64\${INSTALL_DIR}"
# Add version information to the file properties.
VIProductVersion "${PROD_VERSION}"
@ -1465,7 +1465,12 @@ Function .onInit
Call G4wRunOnce
SetOutPath $TEMP
${IfNot} ${RunningX64}
MessageBox MB_OK "Sorry this version runs only on x64 machines"
Abort
${EndIf}
SetOutPath $TEMP
#!ifdef SOURCES
# File /oname=gpgspltmp.bmp "${TOP_SRCDIR}/doc/logo/gnupg-logo-400px.bmp"
# # We play the tune only for the soruce installer
@ -1486,7 +1491,7 @@ Function .onInit
Var /GLOBAL changed_dir
# Check if the install directory was modified on the command line
StrCmp "$INSTDIR" "$PROGRAMFILES\${INSTALL_DIR}" unmodified 0
StrCmp "$INSTDIR" "$PROGRAMFILES64\${INSTALL_DIR}" unmodified 0
# It is modified. Save that value.
StrCpy $changed_dir "$INSTDIR"

View File

@ -61,9 +61,12 @@ and then manually edited:
<Component Id="cmp74961776CCC7B203F500FE261DC12F92" Directory="dirAA72FFDDFA224FB221D53750596B0142" Guid="FBA2569C-554D-4C06-88FC-0FD6541B5B4B">
<File Id="filB82A767EB9971018C006215A9FDE77EF" KeyPath="yes" Source="$(var.SourceDir)\bin\gpg-connect-agent.exe"/>
</Component>
<Component Id="cmp74961776CCC7B203F500FE261DC12F94" Directory="dirAA72FFDDFA224FB221D53750596B0144" Guid="FBA2569C-554D-4C06-88FC-0FD6541B5B4C">
<Component Id="cmp74961776CCC7B203F500FE261DC12F94" Directory="dirAA72FFDDFA224FB221D53750596B0142" Guid="FBA2569C-554D-4C06-88FC-0FD6541B5B4C">
<File Id="filB82A767EB9971018C006215A9FDE77F1" KeyPath="yes" Source="$(var.SourceDir)\bin\gpg-card.exe"/>
</Component>
<Component Id="cmp74961776CCC7B203F500FE261DC12F95" Directory="dirAA72FFDDFA224FB221D53750596B0142" Guid="3134BF55-46AF-4B76-A535-DC1EDDB0DBFD">
<File Id="filB82A767EB9971018C006215A9FDE77F2" KeyPath="yes" Source="$(var.SourceDir)\libexec\keyboxd.exe"/>
</Component>
<Component Id="cmp6C1FB70721B208E33DB24296B93AB93F" Directory="dirAA72FFDDFA224FB221D53750596B0142" Guid="FE29D2AA-3151-4421-B8C0-355F69F267A1">
<File Id="fil563D2C0464DCE7ECADE6E15C0FC65821" KeyPath="yes" Source="$(var.SourceDir)\libexec\gpg-preset-passphrase.exe"/>
</Component>

View File

@ -65,7 +65,7 @@ common_sources = \
homedir.c \
gettime.c gettime.h \
yesno.c \
b64enc.c b64dec.c zb32.c zb32.h \
zb32.c zb32.h \
convert.c \
percent.c \
mbox-util.c mbox-util.h \
@ -97,8 +97,8 @@ common_sources = \
openpgp-fpr.c \
comopt.c comopt.h \
compliance.c compliance.h \
pkscreening.c pkscreening.h
pkscreening.c pkscreening.h \
kem.c
if HAVE_W32_SYSTEM
common_sources += w32-reg.c w32-cmdline.c
@ -161,11 +161,12 @@ module_tests = t-stringhelp t-timestuff \
t-convert t-percent t-gettime t-sysutils t-sexputil \
t-session-env t-openpgp-oid t-ssh-utils \
t-mapstrings t-zb32 t-mbox-util t-iobuf t-strlist \
t-name-value t-ccparray t-recsel t-w32-cmdline t-b64
t-name-value t-ccparray t-recsel t-w32-cmdline t-exechelp
if HAVE_W32_SYSTEM
module_tests += t-w32-reg
else
module_tests += t-exechelp t-exectool
module_tests += t-exectool
endif
if MAINTAINER_MODE
@ -196,7 +197,6 @@ t_gettime_LDADD = $(t_common_ldadd)
t_sysutils_LDADD = $(t_common_ldadd)
t_helpfile_LDADD = $(t_common_ldadd)
t_sexputil_LDADD = $(t_common_ldadd)
t_b64_LDADD = $(t_common_ldadd)
t_exechelp_LDADD = $(t_common_ldadd)
t_exectool_LDADD = $(t_common_ldadd)
t_session_env_LDADD = $(t_common_ldadd)

View File

@ -386,7 +386,8 @@ start_new_service (assuan_context_t *r_ctx,
const char *opt_lc_ctype,
const char *opt_lc_messages,
session_env_t session_env,
int autostart, int verbose, int debug,
unsigned int flags,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg)
{
@ -445,7 +446,7 @@ start_new_service (assuan_context_t *r_ctx,
}
err = assuan_socket_connect (ctx, sockname, 0, connect_flags);
if (err && autostart)
if (err && (flags & ASSHELP_FLAG_AUTOSTART))
{
char *abs_homedir;
lock_spawn_t lock;
@ -523,16 +524,12 @@ start_new_service (assuan_context_t *r_ctx,
&& assuan_socket_connect (ctx, sockname, 0, connect_flags))
{
#ifdef HAVE_W32_SYSTEM
err = gnupg_spawn_process_detached (program? program : program_name,
argv, NULL);
err = gnupg_process_spawn (program? program : program_name, argv,
GNUPG_PROCESS_DETACHED,
NULL, NULL, NULL);
#else /*!W32*/
pid_t pid;
err = gnupg_spawn_process_fd (program? program : program_name,
argv, -1, -1, -1, &pid);
if (!err)
err = gnupg_wait_process (program? program : program_name,
pid, 1, NULL);
err = gnupg_process_spawn (program? program : program_name, argv,
0, NULL, NULL, NULL);
#endif /*!W32*/
if (err)
log_error ("failed to start %s '%s': %s\n",
@ -551,7 +548,8 @@ start_new_service (assuan_context_t *r_ctx,
xfree (sockname);
if (err)
{
if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
if ((flags & ASSHELP_FLAG_AUTOSTART)
|| gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
log_error ("can't connect to the %s: %s\n",
printed_name, gpg_strerror (err));
assuan_release (ctx);
@ -603,55 +601,58 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
const char *opt_lc_ctype,
const char *opt_lc_messages,
session_env_t session_env,
int autostart, int verbose, int debug,
unsigned int flags,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg)
{
return start_new_service (r_ctx, GNUPG_MODULE_NAME_AGENT,
errsource, agent_program,
opt_lc_ctype, opt_lc_messages, session_env,
autostart, verbose, debug,
flags, verbose, debug,
status_cb, status_cb_arg);
}
/* Try to connect to the dirmngr via a socket. On platforms
supporting it, start it up if needed and if AUTOSTART is true.
supporting it, start it up if needed and if ASSHELP_FLAG_AUTOSTART is set.
Returns a new assuan context at R_CTX or an error code. */
gpg_error_t
start_new_keyboxd (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
const char *keyboxd_program,
int autostart, int verbose, int debug,
unsigned int flags,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg)
{
return start_new_service (r_ctx, GNUPG_MODULE_NAME_KEYBOXD,
errsource, keyboxd_program,
NULL, NULL, NULL,
autostart, verbose, debug,
flags, verbose, debug,
status_cb, status_cb_arg);
}
/* Try to connect to the dirmngr via a socket. On platforms
supporting it, start it up if needed and if AUTOSTART is true.
supporting it, start it up if needed and if ASSHELP_FLAG_AUTOSTART is set.
Returns a new assuan context at R_CTX or an error code. */
gpg_error_t
start_new_dirmngr (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
const char *dirmngr_program,
int autostart, int verbose, int debug,
unsigned int flags,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg)
{
#ifndef USE_DIRMNGR_AUTO_START
autostart = 0;
flags &= ~ASSHELP_FLAG_AUTOSTART; /* Clear flag. */
#endif
return start_new_service (r_ctx, GNUPG_MODULE_NAME_DIRMNGR,
errsource, dirmngr_program,
NULL, NULL, NULL,
autostart, verbose, debug,
flags, verbose, debug,
status_cb, status_cb_arg);
}

View File

@ -37,6 +37,8 @@
#include "util.h"
/*-- asshelp.c --*/
#define ASSHELP_FLAG_AUTOSTART 1 /* Autostart the new service. */
void setup_libassuan_logging (unsigned int *debug_var_address,
int (*log_monitor)(assuan_context_t ctx,
@ -61,7 +63,8 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
const char *opt_lc_ctype,
const char *opt_lc_messages,
session_env_t session_env,
int autostart, int verbose, int debug,
unsigned int flags,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg);
@ -71,7 +74,8 @@ gpg_error_t
start_new_keyboxd (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
const char *keyboxd_program,
int autostart, int verbose, int debug,
unsigned int flags,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg);
@ -81,7 +85,8 @@ gpg_error_t
start_new_dirmngr (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
const char *dirmngr_program,
int autostart, int verbose, int debug,
unsigned int flags,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg);

View File

@ -45,8 +45,8 @@ struct log_item_s
int intvalue; /* A logged integer value. */
char *string; /* A malloced string or NULL. */
ksba_cert_t cert; /* A certifciate or NULL. */
int have_err:1;
int have_intvalue:1;
unsigned int have_err:1;
unsigned int have_intvalue:1;
};
typedef struct log_item_s *log_item_t;

View File

@ -1,299 +0,0 @@
/* b64dec.c - Simple Base64 decoder.
* Copyright (C) 2008, 2011 Free Software Foundation, Inc.
* Copyright (C) 2008, 2011, 2016 g10 Code GmbH
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "i18n.h"
#include "util.h"
/* The reverse base-64 list used for base-64 decoding. */
static unsigned char const asctobin[128] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
};
enum decoder_states
{
s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin,
s_b64_0, s_b64_1, s_b64_2, s_b64_3,
s_waitendtitle, s_waitend
};
/* Initialize the context for the base64 decoder. If TITLE is NULL a
plain base64 decoding is done. If it is the empty string the
decoder will skip everything until a "-----BEGIN " line has been
seen, decoding ends at a "----END " line. */
gpg_error_t
b64dec_start (struct b64state *state, const char *title)
{
memset (state, 0, sizeof *state);
if (title)
{
state->title = xtrystrdup (title);
if (!state->title)
state->lasterr = gpg_error_from_syserror ();
else
state->idx = s_init;
}
else
state->idx = s_b64_0;
return state->lasterr;
}
/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the
new length of the buffer at R_NBYTES. */
gpg_error_t
b64dec_proc (struct b64state *state, void *buffer, size_t length,
size_t *r_nbytes)
{
enum decoder_states ds = state->idx;
unsigned char val = state->radbuf[0];
int pos = state->quad_count;
char *d, *s;
if (state->lasterr)
return state->lasterr;
if (state->stop_seen)
{
*r_nbytes = 0;
state->lasterr = gpg_error (GPG_ERR_EOF);
xfree (state->title);
state->title = NULL;
return state->lasterr;
}
for (s=d=buffer; length && !state->stop_seen; length--, s++)
{
again:
switch (ds)
{
case s_idle:
if (*s == '\n')
{
ds = s_lfseen;
pos = 0;
}
break;
case s_init:
ds = s_lfseen;
/* fall through */
case s_lfseen:
if (*s != "-----BEGIN "[pos])
{
ds = s_idle;
goto again;
}
else if (pos == 10)
{
pos = 0;
ds = s_beginseen;
}
else
pos++;
break;
case s_beginseen:
if (*s != "PGP "[pos])
ds = s_begin; /* Not a PGP armor. */
else if (pos == 3)
ds = s_waitheader;
else
pos++;
break;
case s_waitheader:
if (*s == '\n')
ds = s_waitblank;
break;
case s_waitblank:
if (*s == '\n')
ds = s_b64_0; /* blank line found. */
else if (*s == ' ' || *s == '\r' || *s == '\t')
; /* Ignore spaces. */
else
{
/* Armor header line. Note that we don't care that our
* FSM accepts a header prefixed with spaces. */
ds = s_waitheader; /* Wait for next header. */
}
break;
case s_begin:
if (*s == '\n')
ds = s_b64_0;
break;
case s_b64_0:
case s_b64_1:
case s_b64_2:
case s_b64_3:
{
int c;
if (*s == '-' && state->title)
{
/* Not a valid Base64 character: assume end
header. */
ds = s_waitend;
}
else if (*s == '=')
{
/* Pad character: stop */
if (ds == s_b64_1)
*d++ = val;
ds = state->title? s_waitendtitle : s_waitend;
}
else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
; /* Skip white spaces. */
else if ( (*s & 0x80)
|| (c = asctobin[*(unsigned char *)s]) == 255)
{
/* Skip invalid encodings. */
state->invalid_encoding = 1;
}
else if (ds == s_b64_0)
{
val = c << 2;
ds = s_b64_1;
}
else if (ds == s_b64_1)
{
val |= (c>>4)&3;
*d++ = val;
val = (c<<4)&0xf0;
ds = s_b64_2;
}
else if (ds == s_b64_2)
{
val |= (c>>2)&15;
*d++ = val;
val = (c<<6)&0xc0;
ds = s_b64_3;
}
else
{
val |= c&0x3f;
*d++ = val;
ds = s_b64_0;
}
}
break;
case s_waitendtitle:
if (*s == '-')
ds = s_waitend;
break;
case s_waitend:
if ( *s == '\n')
state->stop_seen = 1;
break;
default:
BUG();
}
}
state->idx = ds;
state->radbuf[0] = val;
state->quad_count = pos;
*r_nbytes = (d -(char*) buffer);
return 0;
}
/* This function needs to be called before releasing the decoder
state. It may return an error code in case an encoding error has
been found during decoding. */
gpg_error_t
b64dec_finish (struct b64state *state)
{
xfree (state->title);
state->title = NULL;
if (state->lasterr)
return state->lasterr;
return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0;
}
/* Convert STRING consisting of base64 characters into its binary
* representation and store the result in a newly allocated buffer at
* R_BUFFER with its length at R_BUFLEN. If TITLE is NULL a plain
* base64 decoding is done. If it is the empty string the decoder
* will skip everything until a "-----BEGIN " line has been seen,
* decoding then ends at a "----END " line. On failure the function
* returns an error code and sets R_BUFFER to NULL. If the decoded
* data has a length of 0 a dummy buffer will still be allocated and
* the length is set to 0. */
gpg_error_t
b64decode (const char *string, const char *title,
void **r_buffer, size_t *r_buflen)
{
gpg_error_t err;
struct b64state state;
size_t nbytes;
char *buffer;
*r_buffer = NULL;
*r_buflen = 0;
buffer = xtrystrdup (string);
if (!buffer)
return gpg_error_from_syserror();
err = b64dec_start (&state, title);
if (err)
{
xfree (buffer);
return err;
}
b64dec_proc (&state, buffer, strlen (buffer), &nbytes);
err = b64dec_finish (&state);
if (err)
xfree (buffer);
else
{
*r_buffer = buffer;
*r_buflen = nbytes;
}
return err;
}

View File

@ -1,423 +0,0 @@
/* b64enc.c - Simple Base64 encoder.
* Copyright (C) 2001, 2003, 2004, 2008, 2010,
* 2011 Free Software Foundation, Inc.
* Copyright (C) 2001, 2003, 2004, 2008, 2010,
* 2011 g10 Code GmbH
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "i18n.h"
#include "util.h"
#define B64ENC_DID_HEADER 1
#define B64ENC_DID_TRAILER 2
#define B64ENC_NO_LINEFEEDS 16
#define B64ENC_USE_PGPCRC 32
/* The base-64 character list */
static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
/* Stuff required to create the OpenPGP CRC. This crc_table has been
created using this code:
#include <stdio.h>
#include <stdint.h>
#define CRCPOLY 0x864CFB
int
main (void)
{
int i, j;
uint32_t t;
uint32_t crc_table[256];
crc_table[0] = 0;
for (i=j=0; j < 128; j++ )
{
t = crc_table[j];
if ( (t & 0x00800000) )
{
t <<= 1;
crc_table[i++] = t ^ CRCPOLY;
crc_table[i++] = t;
}
else
{
t <<= 1;
crc_table[i++] = t;
crc_table[i++] = t ^ CRCPOLY;
}
}
puts ("static const u32 crc_table[256] = {");
for (i=j=0; i < 256; i++)
{
printf ("%s 0x%08lx", j? "":" ", (unsigned long)crc_table[i]);
if (i != 255)
{
putchar (',');
if ( ++j > 5)
{
j = 0;
putchar ('\n');
}
}
}
puts ("\n};");
return 0;
}
*/
#define CRCINIT 0xB704CE
static const u32 crc_table[256] = {
0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a,
0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf,
0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272,
0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e,
0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa,
0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f,
0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b,
0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7,
0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a,
0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af,
0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29,
0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5,
0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1,
0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad,
0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099,
0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375,
0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821,
0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4,
0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049,
0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5,
0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791,
0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52,
0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66,
0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a,
0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337,
0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2,
0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6,
0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a,
0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e,
0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132,
0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506,
0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea,
0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c,
0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9,
0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604,
0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8,
0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc,
0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69,
0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d,
0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1,
0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c,
0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9,
0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538
};
static gpg_error_t
enc_start (struct b64state *state, FILE *fp, estream_t stream,
const char *title)
{
memset (state, 0, sizeof *state);
state->fp = fp;
state->stream = stream;
state->lasterr = 0;
if (title && !*title)
state->flags |= B64ENC_NO_LINEFEEDS;
else if (title)
{
if (!strncmp (title, "PGP ", 4))
{
state->flags |= B64ENC_USE_PGPCRC;
state->crc = CRCINIT;
}
state->title = xtrystrdup (title);
if (!state->title)
state->lasterr = gpg_error_from_syserror ();
}
return state->lasterr;
}
/* Prepare for base-64 writing to the stream FP. If TITLE is not NULL
and not an empty string, this string will be used as the title for
the armor lines, with TITLE being an empty string, we don't write
the header lines and furthermore even don't write any linefeeds.
If TITLE starts with "PGP " the OpenPGP CRC checksum will be
written as well. With TITLE being NULL, we merely don't write
header but make sure that lines are not too long. Note, that we
don't write any output unless at least one byte get written using
b64enc_write. */
gpg_error_t
b64enc_start (struct b64state *state, FILE *fp, const char *title)
{
return enc_start (state, fp, NULL, title);
}
/* Same as b64enc_start but takes an estream. */
gpg_error_t
b64enc_start_es (struct b64state *state, estream_t fp, const char *title)
{
return enc_start (state, NULL, fp, title);
}
static int
my_fputs (const char *string, struct b64state *state)
{
if (state->stream)
return es_fputs (string, state->stream);
else
return fputs (string, state->fp);
}
/* Write NBYTES from BUFFER to the Base 64 stream identified by
STATE. With BUFFER and NBYTES being 0, merely do a fflush on the
stream. */
gpg_error_t
b64enc_write (struct b64state *state, const void *buffer, size_t nbytes)
{
unsigned char radbuf[4];
int idx, quad_count;
const unsigned char *p;
if (state->lasterr)
return state->lasterr;
if (!nbytes)
{
if (buffer)
if (state->stream? es_fflush (state->stream) : fflush (state->fp))
goto write_error;
return 0;
}
if (!(state->flags & B64ENC_DID_HEADER))
{
if (state->title)
{
if ( my_fputs ("-----BEGIN ", state) == EOF
|| my_fputs (state->title, state) == EOF
|| my_fputs ("-----\n", state) == EOF)
goto write_error;
if ( (state->flags & B64ENC_USE_PGPCRC)
&& my_fputs ("\n", state) == EOF)
goto write_error;
}
state->flags |= B64ENC_DID_HEADER;
}
idx = state->idx;
quad_count = state->quad_count;
assert (idx < 4);
memcpy (radbuf, state->radbuf, idx);
if ( (state->flags & B64ENC_USE_PGPCRC) )
{
size_t n;
u32 crc = state->crc;
for (p=buffer, n=nbytes; n; p++, n-- )
crc = ((u32)crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ *p];
state->crc = (crc & 0x00ffffff);
}
for (p=buffer; nbytes; p++, nbytes--)
{
radbuf[idx++] = *p;
if (idx > 2)
{
char tmp[4];
tmp[0] = bintoasc[(*radbuf >> 2) & 077];
tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
tmp[3] = bintoasc[radbuf[2]&077];
if (state->stream)
{
for (idx=0; idx < 4; idx++)
es_putc (tmp[idx], state->stream);
idx = 0;
if (es_ferror (state->stream))
goto write_error;
}
else
{
for (idx=0; idx < 4; idx++)
putc (tmp[idx], state->fp);
idx = 0;
if (ferror (state->fp))
goto write_error;
}
if (++quad_count >= (64/4))
{
quad_count = 0;
if (!(state->flags & B64ENC_NO_LINEFEEDS)
&& my_fputs ("\n", state) == EOF)
goto write_error;
}
}
}
memcpy (state->radbuf, radbuf, idx);
state->idx = idx;
state->quad_count = quad_count;
return 0;
write_error:
state->lasterr = gpg_error_from_syserror ();
if (state->title)
{
xfree (state->title);
state->title = NULL;
}
return state->lasterr;
}
gpg_error_t
b64enc_finish (struct b64state *state)
{
gpg_error_t err = 0;
unsigned char radbuf[4];
int idx, quad_count;
char tmp[4];
if (state->lasterr)
return state->lasterr;
if (!(state->flags & B64ENC_DID_HEADER))
goto cleanup;
/* Flush the base64 encoding */
idx = state->idx;
quad_count = state->quad_count;
assert (idx < 4);
memcpy (radbuf, state->radbuf, idx);
if (idx)
{
tmp[0] = bintoasc[(*radbuf>>2)&077];
if (idx == 1)
{
tmp[1] = bintoasc[((*radbuf << 4) & 060) & 077];
tmp[2] = '=';
tmp[3] = '=';
}
else
{
tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
tmp[2] = bintoasc[((radbuf[1] << 2) & 074) & 077];
tmp[3] = '=';
}
if (state->stream)
{
for (idx=0; idx < 4; idx++)
es_putc (tmp[idx], state->stream);
if (es_ferror (state->stream))
goto write_error;
}
else
{
for (idx=0; idx < 4; idx++)
putc (tmp[idx], state->fp);
if (ferror (state->fp))
goto write_error;
}
if (++quad_count >= (64/4))
{
quad_count = 0;
if (!(state->flags & B64ENC_NO_LINEFEEDS)
&& my_fputs ("\n", state) == EOF)
goto write_error;
}
}
/* Finish the last line and write the trailer. */
if (quad_count
&& !(state->flags & B64ENC_NO_LINEFEEDS)
&& my_fputs ("\n", state) == EOF)
goto write_error;
if ( (state->flags & B64ENC_USE_PGPCRC) )
{
/* Write the CRC. */
my_fputs ("=", state);
radbuf[0] = state->crc >>16;
radbuf[1] = state->crc >> 8;
radbuf[2] = state->crc;
tmp[0] = bintoasc[(*radbuf>>2)&077];
tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
tmp[3] = bintoasc[radbuf[2]&077];
if (state->stream)
{
for (idx=0; idx < 4; idx++)
es_putc (tmp[idx], state->stream);
if (es_ferror (state->stream))
goto write_error;
}
else
{
for (idx=0; idx < 4; idx++)
putc (tmp[idx], state->fp);
if (ferror (state->fp))
goto write_error;
}
if (!(state->flags & B64ENC_NO_LINEFEEDS)
&& my_fputs ("\n", state) == EOF)
goto write_error;
}
if (state->title)
{
if ( my_fputs ("-----END ", state) == EOF
|| my_fputs (state->title, state) == EOF
|| my_fputs ("-----\n", state) == EOF)
goto write_error;
}
goto cleanup;
write_error:
err = gpg_error_from_syserror ();
cleanup:
if (state->title)
{
xfree (state->title);
state->title = NULL;
}
state->fp = NULL;
state->stream = NULL;
state->lasterr = err;
return err;
}

View File

@ -41,7 +41,7 @@ static int initialized;
static int module;
/* This value is used by DSA and RSA checks in addition to the hard
* coded length checks. It allows to increase the required key length
* coded length checks. It allows one to increase the required key length
* using a confue file. */
static unsigned int min_compliant_rsa_length;
@ -139,7 +139,7 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
gcry_mpi_t key[], unsigned int keylength,
const char *curvename)
{
enum { is_rsa, is_dsa, is_elg, is_ecc } algotype;
enum { is_rsa, is_dsa, is_elg, is_ecc, is_kem } algotype;
int result = 0;
if (! initialized)
@ -173,6 +173,10 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
case PUBKEY_ALGO_ELGAMAL:
return 0; /* Signing with Elgamal is not at all supported. */
case PUBKEY_ALGO_KYBER:
algotype = is_kem;
break;
default: /* Unknown. */
return 0;
}
@ -227,6 +231,10 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|| !strcmp (curvename, "brainpoolP512r1")));
break;
case is_kem:
result = 0;
break;
default:
result = 0;
}

View File

@ -34,12 +34,15 @@
#ifndef __MINGW32__
# include <dlfcn.h>
#else
# include <errhandlingapi.h>
# include <handleapi.h>
# include <libloaderapi.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h>
# include "utf8conv.h"
# include "mischelp.h"
# define RTLD_LAZY 0
# ifndef RTLD_LAZY
# define RTLD_LAZY 0
# endif
static inline void *
dlopen (const char *name, int flag)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -73,140 +73,103 @@ gpg_error_t gnupg_create_pipe (int filedes[2]);
void gnupg_close_pipe (int fd);
#define GNUPG_SPAWN_NONBLOCK 16
#define GNUPG_SPAWN_RUN_ASFW 64
#define GNUPG_SPAWN_DETACHED 128
#define GNUPG_SPAWN_KEEP_STDIN 256
#define GNUPG_SPAWN_KEEP_STDOUT 512
#define GNUPG_SPAWN_KEEP_STDERR 1024
/* The opaque type for a subprocess. */
typedef struct gnupg_process *gnupg_process_t;
#ifdef HAVE_W32_SYSTEM
struct spawn_cb_arg;
#ifdef NEED_STRUCT_SPAWN_CB_ARG
struct spawn_cb_arg {
HANDLE hd[3];
HANDLE *inherit_hds;
BOOL allow_foreground_window;
void *arg;
};
#endif
#else
struct spawn_cb_arg {
int fds[3];
int *except_fds;
void *arg;
};
#endif
/* Fork and exec the program PGMNAME.
#define GNUPG_PROCESS_DETACHED (1 << 1)
If R_INFP is NULL connect stdin of the new process to /dev/null; if
it is not NULL store the address of a pointer to a new estream
there. If R_OUTFP is NULL connect stdout of the new process to
/dev/null; if it is not NULL store the address of a pointer to a
new estream there. If R_ERRFP is NULL connect stderr of the new
process to /dev/null; if it is not NULL store the address of a
pointer to a new estream there. On success the pid of the new
process is stored at PID. On error -1 is stored at PID and if
R_OUTFP or R_ERRFP are not NULL, NULL is stored there.
/* Specify how to keep/connect standard fds. */
#define GNUPG_PROCESS_STDIN_PIPE (1 << 8)
#define GNUPG_PROCESS_STDOUT_PIPE (1 << 9)
#define GNUPG_PROCESS_STDERR_PIPE (1 << 10)
#define GNUPG_PROCESS_STDINOUT_SOCKETPAIR (1 << 11)
#define GNUPG_PROCESS_STDIN_KEEP (1 << 12)
#define GNUPG_PROCESS_STDOUT_KEEP (1 << 13)
#define GNUPG_PROCESS_STDERR_KEEP (1 << 14)
#define GNUPG_PROCESS_STDFDS_SETTING ( GNUPG_PROCESS_STDIN_PIPE \
| GNUPG_PROCESS_STDOUT_PIPE | GNUPG_PROCESS_STDERR_PIPE \
| GNUPG_PROCESS_STDINOUT_SOCKETPAIR | GNUPG_PROCESS_STDIN_KEEP \
| GNUPG_PROCESS_STDOUT_KEEP | GNUPG_PROCESS_STDERR_KEEP)
The arguments for the process are expected in the NULL terminated
array ARGV. The program name itself should not be included there.
If PREEXEC is not NULL, the given function will be called right
before the exec.
#define GNUPG_PROCESS_STREAM_NONBLOCK (1 << 16)
IF EXCEPT is not NULL, it is expected to be an ordered list of file
descriptors, terminated by an entry with the value (-1). These
file descriptors won't be closed before spawning a new program.
/* Spawn helper. */
void gnupg_spawn_helper (struct spawn_cb_arg *sca);
Returns 0 on success or an error code. Calling gnupg_wait_process
and gnupg_release_process is required if the function succeeded.
/* Spawn PGMNAME. */
gpg_err_code_t gnupg_process_spawn (const char *pgmname, const char *argv[],
unsigned int flags,
void (*spawn_cb) (struct spawn_cb_arg *),
void *spawn_cb_arg,
gnupg_process_t *r_process);
FLAGS is a bit vector:
/* Get FDs for subprocess I/O. It is the caller which should care
FDs (closing FDs). */
gpg_err_code_t gnupg_process_get_fds (gnupg_process_t process,
unsigned int flags,
int *r_fd_in, int *r_fd_out,
int *r_fd_err);
GNUPG_SPAWN_NONBLOCK
If set the two output streams are created in non-blocking
mode and the input stream is switched to non-blocking mode.
This is merely a convenience feature because the caller
could do the same with gpgrt_set_nonblock. Does not yet
work for Windows.
/* Get STREAMs for subprocess I/O. It is the caller which should care
STREAMs (closing STREAMs). */
gpg_err_code_t gnupg_process_get_streams (gnupg_process_t process,
unsigned int flags,
gpgrt_stream_t *r_fp_in,
gpgrt_stream_t *r_fp_out,
gpgrt_stream_t *r_fp_err);
GNUPG_SPAWN_DETACHED
If set the process will be started as a background process.
This flag is only useful under W32 (but not W32CE) systems,
so that no new console is created and pops up a console
window when starting the server. Does not work on W32CE.
enum gnupg_process_requests
{
/* Portable requests */
GNUPG_PROCESS_NOP = 0,
GNUPG_PROCESS_GET_PROC_ID = 1,
GNUPG_PROCESS_GET_EXIT_ID = 2,
GNUPG_SPAWN_RUN_ASFW
On W32 (but not on W32CE) run AllowSetForegroundWindow for
the child. Note that due to unknown problems this actually
allows SetForegroundWindow for all children of this process.
/* POSIX only */
GNUPG_PROCESS_GET_PID = 16,
GNUPG_PROCESS_GET_WSTATUS = 17,
GNUPG_PROCESS_KILL = 18,
GNUPG_SPAWN_KEEP_STDIN
GNUPG_SPAWN_KEEP_STDOUT
GNUPG_SPAWN_KEEP_STDERR
Do not assign /dev/null to a non-required standard file
descriptor.
/* Windows only */
GNUPG_PROCESS_GET_P_HANDLE = 32,
GNUPG_PROCESS_GET_HANDLES = 33,
GNUPG_PROCESS_GET_EXIT_CODE = 34,
GNUPG_PROCESS_KILL_WITH_EC = 35
};
*/
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
int *execpt, unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
pid_t *pid);
/* Control of a process. */
gpg_err_code_t gnupg_process_ctl (gnupg_process_t process,
unsigned int request, ...);
/* Wait for a single PROCESS. */
gpg_err_code_t gnupg_process_wait (gnupg_process_t process, int hang);
/* Simplified version of gnupg_spawn_process. This function forks and
then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
and ERRFD to stderr (any of them may be -1 to connect them to
/dev/null). The arguments for the process are expected in the NULL
terminated array ARGV. The program name itself should not be
included there. Calling gnupg_wait_process and
gnupg_release_process is required. Returns 0 on success or an
error code. */
gpg_error_t gnupg_spawn_process_fd (const char *pgmname,
const char *argv[],
int infd, int outfd, int errfd,
pid_t *pid);
/* Terminate a PROCESS. */
gpg_err_code_t gnupg_process_terminate (gnupg_process_t process);
/* Release PROCESS resources. */
void gnupg_process_release (gnupg_process_t process);
/* If HANG is true, waits for the process identified by PID to exit;
if HANG is false, checks whether the process has terminated.
PGMNAME should be the same as supplied to the spawn function and is
only used for diagnostics. Return values:
0
The process exited successful. 0 is stored at R_EXITCODE.
GPG_ERR_GENERAL
The process exited without success. The exit code of process
is then stored at R_EXITCODE. An exit code of -1 indicates
that the process terminated abnormally (e.g. due to a signal).
GPG_ERR_TIMEOUT
The process is still running (returned only if HANG is false).
GPG_ERR_INV_VALUE
An invalid PID has been specified.
Other error codes may be returned as well. Unless otherwise noted,
-1 will be stored at R_EXITCODE. R_EXITCODE may be passed as NULL
if the exit code is not required (in that case an error message will
be printed). Note that under Windows PID is not the process id but
the handle of the process. */
gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid, int hang,
int *r_exitcode);
/* Like gnupg_wait_process, but for COUNT processes. */
gpg_error_t gnupg_wait_processes (const char **pgmnames, pid_t *pids,
size_t count, int hang, int *r_exitcodes);
/* Kill a process; that is send an appropriate signal to the process.
gnupg_wait_process must be called to actually remove the process
from the system. An invalid PID is ignored. */
void gnupg_kill_process (pid_t pid);
/* Release the process identified by PID. This function is actually
only required for Windows but it does not harm to always call it.
It is a nop if PID is invalid. */
void gnupg_release_process (pid_t pid);
/* Spawn a new process and immediately detach from it. The name of
the program to exec is PGMNAME and its arguments are in ARGV (the
programname is automatically passed as first argument).
Environment strings in ENVP are set. An error is returned if
pgmname is not executable; to make this work it is necessary to
provide an absolute file name. */
gpg_error_t gnupg_spawn_process_detached (const char *pgmname,
const char *argv[],
const char *envp[] );
/* Wait for a multiple processes. */
gpg_err_code_t gnupg_process_wait_list (gnupg_process_t *process_list,
int count, int hang);
#endif /*GNUPG_COMMON_EXECHELP_H*/

View File

@ -38,10 +38,14 @@
#include <gpg-error.h>
#include <assuan.h>
#include "i18n.h"
#include "logging.h"
#include "membuf.h"
#include "mischelp.h"
#ifdef HAVE_W32_SYSTEM
#define NEED_STRUCT_SPAWN_CB_ARG 1
#endif
#include "exechelp.h"
#include "sysutils.h"
#include "util.h"
@ -301,7 +305,6 @@ copy_buffer_flush (struct copy_buffer *c, estream_t sink)
}
/* Run the program PGMNAME with the command line arguments given in
* the NULL terminates array ARGV. If INPUT is not NULL it will be
* fed to stdin of the process. stderr is logged using log_info and
@ -321,7 +324,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
void *status_cb_value)
{
gpg_error_t err;
pid_t pid = (pid_t) -1;
gnupg_process_t proc = NULL;
estream_t infp = NULL;
estream_t extrafp = NULL;
estream_t outfp = NULL, errfp = NULL;
@ -335,7 +338,6 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
read_and_log_buffer_t fderrstate;
struct copy_buffer *cpbuf_in = NULL, *cpbuf_out = NULL, *cpbuf_extra = NULL;
int quiet = 0;
int dummy_exitcode;
memset (fds, 0, sizeof fds);
memset (&fderrstate, 0, sizeof fderrstate);
@ -411,10 +413,15 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
else
exceptclose[0] = -1;
err = gnupg_spawn_process (pgmname, argv,
exceptclose, GNUPG_SPAWN_NONBLOCK,
input? &infp : NULL,
&outfp, &errfp, &pid);
err = gnupg_process_spawn (pgmname, argv,
((input
? GNUPG_PROCESS_STDIN_PIPE
: 0)
| GNUPG_PROCESS_STDOUT_PIPE
| GNUPG_PROCESS_STDERR_PIPE),
gnupg_spawn_helper, exceptclose, &proc);
gnupg_process_get_streams (proc, GNUPG_PROCESS_STREAM_NONBLOCK,
input? &infp : NULL, &outfp, &errfp);
if (extrapipe[0] != -1)
close (extrapipe[0]);
if (argsave)
@ -546,20 +553,25 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
es_fclose (outfp); outfp = NULL;
es_fclose (errfp); errfp = NULL;
err = gnupg_wait_process (pgmname, pid, 1, quiet? &dummy_exitcode : NULL);
pid = (pid_t)(-1);
err = gnupg_process_wait (proc, 1);
if (!err)
{ /* To be compatible to old wait_process. */
int status;
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &status);
if (status)
err = gpg_error (GPG_ERR_GENERAL);
}
leave:
if (err && pid != (pid_t) -1)
gnupg_kill_process (pid);
if (err && proc)
gnupg_process_terminate (proc);
es_fclose (infp);
es_fclose (extrafp);
es_fclose (outfp);
es_fclose (errfp);
if (pid != (pid_t)(-1))
gnupg_wait_process (pgmname, pid, 1, quiet? &dummy_exitcode : NULL);
gnupg_release_process (pid);
gnupg_process_release (proc);
copy_buffer_shred (cpbuf_in);
xfree (cpbuf_in);

View File

@ -94,7 +94,8 @@ start_agent (void)
agentargs.lc_ctype,
agentargs.lc_messages,
agentargs.session_env,
1, agentargs.verbosity, 0, NULL, NULL);
ASSHELP_FLAG_AUTOSTART,
agentargs.verbosity, 0, NULL, NULL);
if (!err)
{
/* Tell the agent that we support Pinentry notifications. No

View File

@ -1,7 +1,7 @@
/* homedir.c - Setup the home directory.
* Copyright (C) 2004, 2006, 2007, 2010 Free Software Foundation, Inc.
* Copyright (C) 2013, 2016 Werner Koch
* Copyright (C) 2021 g10 Code GmbH
* Copyright (C) 2021, 2024 g10 Code GmbH
*
* This file is part of GnuPG.
*
@ -93,6 +93,22 @@ static char *the_gnupg_homedir;
static byte non_default_homedir;
/* An object to store information taken from a gpgconf.ctl file. This
* is parsed early at startup time and never changed later. */
static struct
{
unsigned int checked:1; /* True if we have checked for a gpgconf.ctl. */
unsigned int found:1; /* True if a gpgconf.ctl was found. */
unsigned int empty:1; /* The file is empty except for comments. */
unsigned int valid:1; /* The entries in gpgconf.ctl are valid. */
unsigned int portable:1;/* Windows portable installation. */
char *gnupg; /* The "gnupg" directory part. */
char *rootdir; /* rootdir or NULL */
char *sysconfdir; /* sysconfdir or NULL */
char *socketdir; /* socketdir or NULL */
} gpgconf_ctl;
#ifdef HAVE_W32_SYSTEM
/* A flag used to indicate that a control file for gpgconf has been
* detected. Under Windows the presence of this file indicates a
@ -119,6 +135,87 @@ static byte w32_bin_is_bin;
static const char *w32_rootdir (void);
#endif
/* Return the name of the gnupg dir. This is usually "gnupg". */
static const char *
my_gnupg_dirname (void)
{
if (gpgconf_ctl.valid && gpgconf_ctl.gnupg)
return gpgconf_ctl.gnupg;
return "gnupg";
}
/* Return the hardwired home directory which is not anymore so
* hardwired because it may now be modified using the gpgconf.ctl
* "gnupg" keyword. */
static const char *
my_fixed_default_homedir (void)
{
if (gpgconf_ctl.valid && gpgconf_ctl.gnupg)
{
static char *name;
char *p;
if (!name)
{
name = xmalloc (strlen (GNUPG_DEFAULT_HOMEDIR)
+ strlen (gpgconf_ctl.gnupg) + 1);
strcpy (name, GNUPG_DEFAULT_HOMEDIR);
p = strrchr (name, '/');
if (p)
p++;
else
p = name;
if (*p == '.')
p++; /* Keep a leading dot. */
strcpy (p, gpgconf_ctl.gnupg);
gpgrt_annotate_leaked_object (name);
}
return name;
}
return GNUPG_DEFAULT_HOMEDIR;
}
/* Under Windows we need to modify the standard registry key with the
* "gnupg" keyword from a gpgconf.ctl. */
#ifdef HAVE_W32_SYSTEM
const char *
gnupg_registry_dir (void)
{
if (gpgconf_ctl.valid && gpgconf_ctl.gnupg)
{
static char *name;
char *p;
if (!name)
{
name = xmalloc (strlen (GNUPG_REGISTRY_DIR)
+ strlen (gpgconf_ctl.gnupg) + 1);
strcpy (name, GNUPG_REGISTRY_DIR);
p = strrchr (name, '\\');
if (p)
p++;
else
p = name;
strcpy (p, gpgconf_ctl.gnupg);
if (!strncmp (p, "gnupg", 5))
{
/* Registry keys are case-insensitive and we use a
* capitalized version of gnupg by default. So, if the
* new value starts with "gnupg" we apply the usual
* capitalization for this first part. */
p[0] = 'G';
p[3] = 'P';
p[4] = 'G';
}
gpgrt_annotate_leaked_object (name);
}
return name;
}
return GNUPG_REGISTRY_DIR;
}
#endif /*HAVE_W32_SYSTEM*/
/* This is a helper function to load and call a Windows function from
@ -324,7 +421,7 @@ standard_homedir (void)
NULL, 0);
if (path)
{
dir = xstrconcat (path, "\\gnupg", NULL);
dir = xstrconcat (path, "\\", my_gnupg_dirname (), NULL);
xfree (path);
gpgrt_annotate_leaked_object (dir);
@ -335,12 +432,12 @@ standard_homedir (void)
}
else
dir = GNUPG_DEFAULT_HOMEDIR;
dir = my_fixed_default_homedir ();
}
}
return dir;
#else/*!HAVE_W32_SYSTEM*/
return GNUPG_DEFAULT_HOMEDIR;
return my_fixed_default_homedir ();
#endif /*!HAVE_W32_SYSTEM*/
}
@ -374,7 +471,7 @@ default_homedir (void)
* warning if the homedir has been taken from the
* registry. */
tmp = read_w32_registry_string (NULL,
GNUPG_REGISTRY_DIR,
gnupg_registry_dir (),
"HomeDir");
if (tmp && !*tmp)
{
@ -399,7 +496,7 @@ default_homedir (void)
#endif /*HAVE_W32_SYSTEM*/
if (!dir || !*dir)
dir = GNUPG_DEFAULT_HOMEDIR;
dir = my_fixed_default_homedir ();
else
{
char *p;
@ -427,6 +524,234 @@ default_homedir (void)
}
/* Return true if S can be inteprtated as true. This is uised for
* keywords in gpgconf.ctl. Spaces must have been trimmed. */
static int
string_is_true (const char *s)
{
return (atoi (s)
|| !ascii_strcasecmp (s, "yes")
|| !ascii_strcasecmp (s, "true")
|| !ascii_strcasecmp (s, "fact"));
}
/* This function is used to parse the gpgconf.ctl file and set the
* information ito the gpgconf_ctl structure. This is called once
* with the full filename of gpgconf.ctl. There are two callers: One
* used on Windows and one on Unix. No error return but diagnostics
* are printed. */
static void
parse_gpgconf_ctl (const char *fname)
{
gpg_error_t err;
char *p;
char *line;
size_t linelen;
ssize_t length;
estream_t fp;
const char *name;
int anyitem = 0;
int ignoreall = 0;
char *gnupgval = NULL;
char *rootdir = NULL;
char *sysconfdir = NULL;
char *socketdir = NULL;
if (gpgconf_ctl.checked)
return; /* Just in case this is called a second time. */
gpgconf_ctl.checked = 1;
gpgconf_ctl.found = 0;
gpgconf_ctl.valid = 0;
gpgconf_ctl.empty = 0;
if (gnupg_access (fname, F_OK))
return; /* No gpgconf.ctl file. */
/* log_info ("detected '%s'\n", buffer); */
fp = es_fopen (fname, "r");
if (!fp)
{
err = gpg_error_from_syserror ();
log_info ("error opening '%s': %s\n", fname, gpg_strerror (err));
return;
}
gpgconf_ctl.found = 1;
line = NULL;
linelen = 0;
while ((length = es_read_line (fp, &line, &linelen, NULL)) > 0)
{
static const char *names[] =
{
"gnupg",
"rootdir",
"sysconfdir",
"socketdir",
"portable",
".enable"
};
int i;
size_t n;
/* Strip NL and CR, if present. */
while (length > 0
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
line[--length] = 0;
trim_spaces (line);
if (*line == '#' || !*line)
continue;
anyitem = 1;
/* Find the keyword. */
name = NULL;
p = NULL;
for (i=0; i < DIM (names); i++)
{
n = strlen (names[i]);
if (!strncmp (line, names[i], n))
{
while (line[n] == ' ' || line[n] == '\t')
n++;
if (line[n] == '=')
{
name = names[i];
p = line + n + 1;
break;
}
}
}
if (!name)
continue; /* Keyword not known. */
trim_spaces (p);
p = substitute_envvars (p);
if (!p)
{
err = gpg_error_from_syserror ();
log_info ("error getting %s from gpgconf.ctl: %s\n",
name, gpg_strerror (err));
}
else if (!strcmp (name, ".enable"))
{
if (string_is_true (p))
; /* Yes, this file shall be used. */
else
ignoreall = 1; /* No, this file shall be ignored. */
xfree (p);
}
else if (!strcmp (name, "gnupg"))
{
xfree (gnupgval);
gnupgval = p;
}
else if (!strcmp (name, "sysconfdir"))
{
xfree (sysconfdir);
sysconfdir = p;
}
else if (!strcmp (name, "socketdir"))
{
xfree (socketdir);
socketdir = p;
}
else if (!strcmp (name, "rootdir"))
{
xfree (rootdir);
rootdir = p;
}
else if (!strcmp (name, "portable"))
{
gpgconf_ctl.portable = string_is_true (p);
xfree (p);
}
else /* Unknown keyword. */
xfree (p);
}
if (es_ferror (fp))
{
err = gpg_error_from_syserror ();
log_info ("error reading '%s': %s\n", fname, gpg_strerror (err));
ignoreall = 1; /* Force all entries to invalid. */
}
es_fclose (fp);
xfree (line);
if (ignoreall)
; /* Forced error. Note that .found is still set. */
else if (gnupgval && (!*gnupgval || strpbrk (gnupgval, "/\\")))
{
/* We don't allow a slash or backslash in the value because our
* code assumes this is a single directory name. */
log_info ("invalid %s '%s' specified in gpgconf.ctl\n",
"gnupg", gnupgval);
}
else if (rootdir && (!*rootdir || *rootdir != '/'))
{
log_info ("invalid %s '%s' specified in gpgconf.ctl\n",
"rootdir", rootdir);
}
else if (sysconfdir && (!*sysconfdir || *sysconfdir != '/'))
{
log_info ("invalid %s '%s' specified in gpgconf.ctl\n",
"sysconfdir", sysconfdir);
}
else if (socketdir && (!*socketdir || *socketdir != '/'))
{
log_info ("invalid %s '%s' specified in gpgconf.ctl\n",
"socketdir", socketdir);
}
else
{
if (gnupgval)
{
gpgconf_ctl.gnupg = gnupgval;
gpgrt_annotate_leaked_object (gpgconf_ctl.gnupg);
/* log_info ("want gnupg '%s'\n", dir); */
}
if (rootdir)
{
while (*rootdir && rootdir[strlen (rootdir)-1] == '/')
rootdir[strlen (rootdir)-1] = 0;
gpgconf_ctl.rootdir = rootdir;
gpgrt_annotate_leaked_object (gpgconf_ctl.rootdir);
/* log_info ("want rootdir '%s'\n", dir); */
}
if (sysconfdir)
{
while (*sysconfdir && sysconfdir[strlen (sysconfdir)-1] == '/')
sysconfdir[strlen (sysconfdir)-1] = 0;
gpgconf_ctl.sysconfdir = sysconfdir;
gpgrt_annotate_leaked_object (gpgconf_ctl.sysconfdir);
/* log_info ("want sysconfdir '%s'\n", sdir); */
}
if (socketdir)
{
while (*socketdir && socketdir[strlen (socketdir)-1] == '/')
socketdir[strlen (socketdir)-1] = 0;
gpgconf_ctl.socketdir = socketdir;
gpgrt_annotate_leaked_object (gpgconf_ctl.socketdir);
/* log_info ("want socketdir '%s'\n", s2dir); */
}
gpgconf_ctl.valid = 1;
}
gpgconf_ctl.empty = !anyitem;
if (!gpgconf_ctl.valid)
{
/* Error reading some entries - clear them all. */
xfree (gnupgval);
xfree (rootdir);
xfree (sysconfdir);
xfree (socketdir);
gpgconf_ctl.gnupg = NULL;
gpgconf_ctl.rootdir = NULL;
gpgconf_ctl.sysconfdir = NULL;
gpgconf_ctl.socketdir = NULL;
}
}
#ifdef HAVE_W32_SYSTEM
/* Check whether gpgconf is installed and if so read the gpgconf.ctl
file. */
@ -439,17 +764,20 @@ check_portable_app (const char *dir)
if (!gnupg_access (fname, F_OK))
{
strcpy (fname + strlen (fname) - 3, "ctl");
if (!gnupg_access (fname, F_OK))
parse_gpgconf_ctl (fname);
if ((gpgconf_ctl.found && gpgconf_ctl.empty)
|| (gpgconf_ctl.valid && gpgconf_ctl.portable))
{
/* gpgconf.ctl file found. Record this fact. */
unsigned int flags;
/* Classic gpgconf.ctl file found. This is a portable
* application. Note that if there are any items in that
* file we don't consider this a portable application unless
* the (later added) ".portable" keyword has also been
* seen. */
w32_portable_app = 1;
{
unsigned int flags;
log_get_prefix (&flags);
log_set_prefix (NULL, (flags | GPGRT_LOG_NO_REGISTRY));
}
/* FIXME: We should read the file to detect special flags
and print a warning if we don't understand them */
log_get_prefix (&flags);
log_set_prefix (NULL, (flags | GPGRT_LOG_NO_REGISTRY));
}
}
xfree (fname);
@ -528,28 +856,14 @@ w32_rootdir (void)
static const char *
unix_rootdir (enum wantdir_values wantdir)
{
static int checked;
static char *dir; /* for the rootdir */
static char *sdir; /* for the sysconfdir */
static char *s2dir; /* for the socketdir */
if (!checked)
if (!gpgconf_ctl.checked)
{
char *p;
char *buffer;
size_t bufsize = 256-1;
int nread;
gpg_error_t err;
char *line;
size_t linelen;
ssize_t length;
estream_t fp;
char *rootdir;
char *sysconfdir;
char *socketdir;
const char *name;
int ignoreall = 0;
int okay;
for (;;)
{
@ -589,7 +903,7 @@ unix_rootdir (enum wantdir_values wantdir)
if (!*buffer)
{
xfree (buffer);
checked = 1;
gpgconf_ctl.checked = 1;
return NULL; /* Error - assume no gpgconf.ctl. */
}
@ -597,197 +911,36 @@ unix_rootdir (enum wantdir_values wantdir)
if (!p)
{
xfree (buffer);
checked = 1;
gpgconf_ctl.checked = 1;
return NULL; /* Erroneous /proc - assume no gpgconf.ctl. */
}
*p = 0; /* BUFFER has the directory. */
if ((p = strrchr (buffer, '/')))
{
/* Strip one part and expect the file below a bin dir. */
*p = 0;
p = xstrconcat (buffer, "/bin/gpgconf.ctl", NULL);
xfree (buffer);
buffer = p;
}
else /* !p */
if (!(p = strrchr (buffer, '/')))
{
/* Installed in the root which is not a good idea. Assume
* no gpgconf.ctl. */
xfree (buffer);
checked = 1;
gpgconf_ctl.checked = 1;
return NULL;
}
if (gnupg_access (buffer, F_OK))
{
/* No gpgconf.ctl file. */
xfree (buffer);
checked = 1;
return NULL;
}
/* log_info ("detected '%s'\n", buffer); */
fp = es_fopen (buffer, "r");
if (!fp)
{
err = gpg_error_from_syserror ();
log_info ("error opening '%s': %s\n", buffer, gpg_strerror (err));
xfree (buffer);
checked = 1;
return NULL;
}
line = NULL;
linelen = 0;
rootdir = NULL;
sysconfdir = NULL;
socketdir = NULL;
while ((length = es_read_line (fp, &line, &linelen, NULL)) > 0)
{
static const char *names[] =
{
"rootdir",
"sysconfdir",
"socketdir",
".enable"
};
int i;
size_t n;
/* Strip NL and CR, if present. */
while (length > 0
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
line[--length] = 0;
trim_spaces (line);
/* Find the stamement. */
name = NULL;
for (i=0; i < DIM (names); i++)
{
n = strlen (names[i]);
if (!strncmp (line, names[i], n))
{
while (line[n] == ' ' || line[n] == '\t')
n++;
if (line[n] == '=')
{
name = names[i];
p = line + n + 1;
break;
}
}
}
if (!name)
continue; /* Statement not known. */
trim_spaces (p);
p = substitute_envvars (p);
if (!p)
{
err = gpg_error_from_syserror ();
log_info ("error getting %s from gpgconf.ctl: %s\n",
name, gpg_strerror (err));
}
else if (!strcmp (name, ".enable"))
{
if (atoi (p)
|| !ascii_strcasecmp (p, "yes")
|| !ascii_strcasecmp (p, "true")
|| !ascii_strcasecmp (p, "fact"))
; /* Yes, this file shall be used. */
else
ignoreall = 1; /* No, this file shall be ignored. */
xfree (p);
}
else if (!strcmp (name, "sysconfdir"))
{
xfree (sysconfdir);
sysconfdir = p;
}
else if (!strcmp (name, "socketdir"))
{
xfree (socketdir);
socketdir = p;
}
else
{
xfree (rootdir);
rootdir = p;
}
}
if (es_ferror (fp))
{
err = gpg_error_from_syserror ();
log_info ("error reading '%s': %s\n", buffer, gpg_strerror (err));
es_fclose (fp);
xfree (buffer);
xfree (line);
xfree (rootdir);
xfree (sysconfdir);
xfree (socketdir);
checked = 1;
return NULL;
}
es_fclose (fp);
/* Strip one part and expect the file below a bin dir. */
*p = 0;
p = xstrconcat (buffer, "/bin/gpgconf.ctl", NULL);
xfree (buffer);
buffer = p;
parse_gpgconf_ctl (buffer);
xfree (buffer);
xfree (line);
okay = 0;
if (ignoreall)
;
else if (!rootdir || !*rootdir || *rootdir != '/')
{
log_info ("invalid rootdir '%s' specified in gpgconf.ctl\n", rootdir);
}
else if (sysconfdir && (!*sysconfdir || *sysconfdir != '/'))
{
log_info ("invalid sysconfdir '%s' specified in gpgconf.ctl\n",
sysconfdir);
}
else if (socketdir && (!*socketdir || *socketdir != '/'))
{
log_info ("invalid socketdir '%s' specified in gpgconf.ctl\n",
socketdir);
}
else
{
okay = 1;
while (*rootdir && rootdir[strlen (rootdir)-1] == '/')
rootdir[strlen (rootdir)-1] = 0;
dir = rootdir;
gpgrt_annotate_leaked_object (dir);
/* log_info ("want rootdir '%s'\n", dir); */
if (sysconfdir)
{
while (*sysconfdir && sysconfdir[strlen (sysconfdir)-1] == '/')
sysconfdir[strlen (sysconfdir)-1] = 0;
sdir = sysconfdir;
gpgrt_annotate_leaked_object (sdir);
/* log_info ("want sysconfdir '%s'\n", sdir); */
}
if (socketdir)
{
while (*socketdir && socketdir[strlen (socketdir)-1] == '/')
socketdir[strlen (socketdir)-1] = 0;
s2dir = socketdir;
gpgrt_annotate_leaked_object (s2dir);
/* log_info ("want socketdir '%s'\n", s2dir); */
}
}
if (!okay)
{
xfree (rootdir);
xfree (sysconfdir);
xfree (socketdir);
dir = sdir = s2dir = NULL;
}
checked = 1;
}
if (!gpgconf_ctl.valid)
return NULL; /* No valid entries in gpgconf.ctl */
switch (wantdir)
{
case WANTDIR_ROOT: return dir;
case WANTDIR_SYSCONF: return sdir;
case WANTDIR_SOCKET: return s2dir;
case WANTDIR_ROOT: return gpgconf_ctl.rootdir;
case WANTDIR_SYSCONF: return gpgconf_ctl.sysconfdir;
case WANTDIR_SOCKET: return gpgconf_ctl.socketdir;
}
return NULL; /* Not reached. */
@ -982,7 +1135,7 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
if (w32_portable_app)
{
name = xstrconcat (w32_rootdir (), DIRSEP_S, "gnupg", NULL);
name = xstrconcat (w32_rootdir (), DIRSEP_S, my_gnupg_dirname (), NULL);
}
else
{
@ -993,7 +1146,7 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
NULL, 0);
if (path)
{
name = xstrconcat (path, "\\gnupg", NULL);
name = xstrconcat (path, "\\", my_gnupg_dirname (), NULL);
xfree (path);
if (gnupg_access (name, F_OK))
gnupg_mkdir (name, "-rwx");
@ -1101,10 +1254,11 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
};
int i;
struct stat sb;
char prefixbuffer[19 + 1 + 20 + 6 + 1];
char prefixbuffer[256];
const char *prefix;
const char *s;
char *name = NULL;
const char *gnupgname = my_gnupg_dirname ();
*r_info = 0;
@ -1143,12 +1297,13 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
goto leave;
}
if (strlen (prefix) + 7 >= sizeof prefixbuffer)
if (strlen (prefix) + strlen (gnupgname) + 2 >= sizeof prefixbuffer)
{
*r_info |= 1; /* Ooops: Buffer too short to append "/gnupg". */
goto leave;
}
strcat (prefixbuffer, "/gnupg");
strcat (prefixbuffer, "/");
strcat (prefixbuffer, gnupgname);
}
/* Check whether the gnupg sub directory (or the specified diretory)
@ -1303,11 +1458,8 @@ gnupg_sysconfdir (void)
if (!name)
{
const char *s1, *s2;
s1 = w32_commondir ();
s2 = DIRSEP_S "etc" DIRSEP_S "gnupg";
name = xmalloc (strlen (s1) + strlen (s2) + 1);
strcpy (stpcpy (name, s1), s2);
name = xstrconcat (w32_commondir (), DIRSEP_S, "etc", DIRSEP_S,
my_gnupg_dirname (), NULL);
gpgrt_annotate_leaked_object (name);
}
return name;

View File

@ -37,6 +37,7 @@
# include <winsock2.h>
# endif
# include <windows.h>
# include <wctype.h>
#endif
#include <gcrypt.h>

View File

@ -166,7 +166,8 @@ block_filter_ctx_t;
/* Local prototypes. */
static int underflow (iobuf_t a, int clear_pending_eof);
static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target);
static int translate_file_handle (int fd, int for_write);
static iobuf_t do_iobuf_fdopen (gnupg_fd_t fp, const char *mode, int keep_open);
/* Sends any pending data to the filter's FILTER function. Note: this
works on the filter and not on the whole pipeline. That is,
@ -389,7 +390,7 @@ fd_cache_close (const char *fname, gnupg_fd_t fp)
close (fp);
#endif
if (DBG_IOBUF)
log_debug ("fd_cache_close (%d) real\n", (int)fp);
log_debug ("fd_cache_close (%d) real\n", FD_DBG (fp));
return;
}
/* try to reuse a slot */
@ -696,7 +697,7 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
if (f != FD_FOR_STDIN && f != FD_FOR_STDOUT)
{
if (DBG_IOBUF)
log_debug ("%s: close fd/handle %d\n", a->fname, FD2INT (f));
log_debug ("%s: close fd/handle %d\n", a->fname, FD_DBG (f));
if (!a->keep_open)
fd_cache_close (a->no_cache ? NULL : a->fname, f);
}
@ -1410,7 +1411,7 @@ iobuf_is_pipe_filename (const char *fname)
{
if (!fname || (*fname=='-' && !fname[1]) )
return 1;
return check_special_filename (fname, 0, 1) != -1;
return gnupg_check_special_filename (fname) != GNUPG_INVALID_FD;
}
@ -1423,7 +1424,7 @@ do_open (const char *fname, int special_filenames,
file_filter_ctx_t *fcx;
size_t len = 0;
int print_only = 0;
int fd;
gnupg_fd_t fd;
byte desc[MAX_IOBUF_DESC];
log_assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT);
@ -1447,9 +1448,8 @@ do_open (const char *fname, int special_filenames,
else if (!fname)
return NULL;
else if (special_filenames
&& (fd = check_special_filename (fname, 0, 1)) != -1)
return iobuf_fdopen (translate_file_handle (fd, use == IOBUF_INPUT ? 0 : 1),
opentype);
&& (fd = gnupg_check_special_filename (fname)) != GNUPG_INVALID_FD)
return do_iobuf_fdopen (fd, opentype, 0);
else
{
if (use == IOBUF_INPUT)
@ -1472,7 +1472,8 @@ do_open (const char *fname, int special_filenames,
file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
if (DBG_IOBUF)
log_debug ("iobuf-%d.%d: open '%s' desc=%s fd=%d\n",
a->no, a->subno, fname, iobuf_desc (a, desc), FD2INT (fcx->fp));
a->no, a->subno, fname, iobuf_desc (a, desc),
FD_DBG (fcx->fp));
return a;
}
@ -1497,22 +1498,19 @@ iobuf_openrw (const char *fname)
static iobuf_t
do_iobuf_fdopen (int fd, const char *mode, int keep_open)
do_iobuf_fdopen (gnupg_fd_t fp, const char *mode, int keep_open)
{
iobuf_t a;
gnupg_fd_t fp;
file_filter_ctx_t *fcx;
size_t len = 0;
fp = INT2FD (fd);
a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
iobuf_buffer_size);
fcx = xmalloc (sizeof *fcx + 20);
fcx->fp = fp;
fcx->print_only_name = 1;
fcx->keep_open = keep_open;
sprintf (fcx->fname, "[fd %d]", fd);
sprintf (fcx->fname, "[fd %d]", FD_DBG (fp));
a->filter = file_filter;
a->filter_ov = fcx;
file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
@ -1525,15 +1523,15 @@ do_iobuf_fdopen (int fd, const char *mode, int keep_open)
iobuf_t
iobuf_fdopen (int fd, const char *mode)
iobuf_fdopen (gnupg_fd_t fp, const char *mode)
{
return do_iobuf_fdopen (fd, mode, 0);
return do_iobuf_fdopen (fp, mode, 0);
}
iobuf_t
iobuf_fdopen_nc (int fd, const char *mode)
iobuf_fdopen_nc (gnupg_fd_t fp, const char *mode)
{
return do_iobuf_fdopen (fd, mode, 1);
return do_iobuf_fdopen (fp, mode, 1);
}
@ -1585,7 +1583,7 @@ iobuf_sockopen (int fd, const char *mode)
log_debug ("iobuf-%d.%d: sockopen '%s'\n", a->no, a->subno, scx->fname);
iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
#else
a = iobuf_fdopen (fd, mode);
a = do_iobuf_fdopen (fd, mode, 0);
#endif
return a;
}
@ -2644,20 +2642,20 @@ iobuf_get_filelength (iobuf_t a)
}
int
gnupg_fd_t
iobuf_get_fd (iobuf_t a)
{
for (; a->chain; a = a->chain)
;
if (a->filter != file_filter)
return -1;
return GNUPG_INVALID_FD;
{
file_filter_ctx_t *b = a->filter_ov;
gnupg_fd_t fp = b->fp;
return FD2INT (fp);
return fp;
}
}
@ -2948,36 +2946,6 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
return nbytes;
}
static int
translate_file_handle (int fd, int for_write)
{
#if defined(HAVE_W32_SYSTEM)
{
int x;
(void)for_write;
if (fd == 0)
x = (int) GetStdHandle (STD_INPUT_HANDLE);
else if (fd == 1)
x = (int) GetStdHandle (STD_OUTPUT_HANDLE);
else if (fd == 2)
x = (int) GetStdHandle (STD_ERROR_HANDLE);
else
x = fd;
if (x == -1)
log_debug ("GetStdHandle(%d) failed: ec=%d\n",
fd, (int) GetLastError ());
fd = x;
}
#else
(void)for_write;
#endif
return fd;
}
void
iobuf_skip_rest (iobuf_t a, unsigned long n, int partial)

View File

@ -333,11 +333,11 @@ iobuf_t iobuf_openrw (const char *fname);
creates an input filter. Note: MODE must reflect the file
descriptors actual mode! When the filter is destroyed, the file
descriptor is closed. */
iobuf_t iobuf_fdopen (int fd, const char *mode);
iobuf_t iobuf_fdopen (gnupg_fd_t fd, const char *mode);
/* Like iobuf_fdopen, but doesn't close the file descriptor when the
filter is destroyed. */
iobuf_t iobuf_fdopen_nc (int fd, const char *mode);
iobuf_t iobuf_fdopen_nc (gnupg_fd_t fd, const char *mode);
/* Create a filter using an existing estream. If MODE contains the
letter 'w', creates an output filter. Otherwise, creates an input
@ -590,7 +590,7 @@ uint64_t iobuf_get_filelength (iobuf_t a);
/* Return the file descriptor designating the underlying file. This
only works with file_filter based pipelines. */
int iobuf_get_fd (iobuf_t a);
gnupg_fd_t iobuf_get_fd (iobuf_t a);
/* Return the real filename, if available. This only supports
pipelines that end in file filters. Returns NULL if not

220
common/kem.c Normal file
View File

@ -0,0 +1,220 @@
/* kem.c - KEM helper functions
* Copyright (C) 2024 g10 Code GmbH.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute and/or modify this
* part of GnuPG under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* GnuPG is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received copies of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later)
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <gpg-error.h>
#include <gcrypt.h>
#include "mischelp.h"
/* domSeperation as per *PGP specs. */
#define KMAC_KEY "OpenPGPCompositeKeyDerivationFunction"
/* customizationString as per *PGP specs. */
#define KMAC_CUSTOM "KDF"
/* The blocksize used for Keccak by compute_kmac256. */
#define KECCAK512_BLOCKSIZE 136
static gpg_error_t
compute_kmac256 (void *digest, size_t digestlen,
const void *key, size_t keylen,
const void *custom, size_t customlen,
gcry_buffer_t *data_iov, int data_iovlen)
{
gpg_error_t err;
gcry_buffer_t iov[20];
const unsigned char headPAD[2] = { 1, KECCAK512_BLOCKSIZE };
unsigned char headK[3];
const unsigned char pad[KECCAK512_BLOCKSIZE] = { 0 };
unsigned char right_encode_L[3];
unsigned int len;
int iovcnt;
if (data_iovlen >= DIM(iov) - 6)
return gpg_error (GPG_ERR_TOO_LARGE);
/* Check the validity conditions of NIST SP 800-185 */
if (keylen >= 255 || customlen >= 255 || digestlen >= 255)
return gpg_error (GPG_ERR_TOO_LARGE);
iovcnt = 0;
iov[iovcnt].data = "KMAC";
iov[iovcnt].off = 0;
iov[iovcnt].len = 4;
iovcnt++;
iov[iovcnt].data = (void *)custom;
iov[iovcnt].off = 0;
iov[iovcnt].len = customlen;
iovcnt++;
iov[iovcnt].data = (void *)headPAD;
iov[iovcnt].off = 0;
iov[iovcnt].len = sizeof (headPAD);
iovcnt++;
if (keylen < 32)
{
headK[0] = 1;
headK[1] = (keylen*8)&0xff;
iov[iovcnt].data = headK;
iov[iovcnt].off = 0;
iov[iovcnt].len = 2;
}
else
{
headK[0] = 2;
headK[1] = (keylen*8)>>8;
headK[2] = (keylen*8)&0xff;
iov[iovcnt].data = headK;
iov[iovcnt].off = 0;
iov[iovcnt].len = 3;
}
iovcnt++;
iov[iovcnt].data = (void *)key;
iov[iovcnt].off = 0;
iov[iovcnt].len = keylen;
iovcnt++;
len = iov[2].len + iov[3].len + iov[4].len;
len %= KECCAK512_BLOCKSIZE;
iov[iovcnt].data = (unsigned char *)pad;
iov[iovcnt].off = 0;
iov[iovcnt].len = sizeof (pad) - len;
iovcnt++;
memcpy (&iov[iovcnt], data_iov, data_iovlen * sizeof (gcry_buffer_t));
iovcnt += data_iovlen;
if (digestlen < 32)
{
right_encode_L[0] = (digestlen * 8) & 0xff;
right_encode_L[1] = 1;
}
else
{
right_encode_L[0] = (digestlen * 8) >> 8;
right_encode_L[1] = (digestlen * 8) & 0xff;
right_encode_L[2] = 2;
}
iov[iovcnt].data = right_encode_L;
iov[iovcnt].off = 0;
iov[iovcnt].len = 3;
iovcnt++;
err = gcry_md_hash_buffers_ext (GCRY_MD_CSHAKE256, 0,
digest, digestlen, iov, iovcnt);
return err;
}
/* Compute KEK (shared secret) for ECC with HASHALGO, ECDH result,
ciphertext in ECC_CT, public key in ECC_PK. */
gpg_error_t
gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
int hashalgo, const void *ecdh, size_t ecdh_len,
const void *ecc_ct, size_t ecc_ct_len,
const void *ecc_pk, size_t ecc_pk_len)
{
gcry_buffer_t iov[3];
unsigned int dlen;
dlen = gcry_md_get_algo_dlen (hashalgo);
if (kek_len != dlen)
return gpg_error (GPG_ERR_INV_LENGTH);
memset (iov, 0, sizeof (iov));
iov[0].data = (unsigned char *)ecdh;
iov[0].len = ecdh_len;
iov[1].data = (unsigned char *)ecc_ct;
iov[1].len = ecc_ct_len;
iov[2].data = (unsigned char *)ecc_pk;
iov[2].len = ecc_pk_len;
gcry_md_hash_buffers (hashalgo, 0, kek, iov, 3);
return 0;
}
/* Compute KEK by combining two KEMs. The caller provides a buffer
* KEK allocated with size KEK_LEN which will receive the computed
* KEK. (ECC_SS, ECC_SS_LEN) is the shared secret of the first key.
* (ECC_CT, ECC_CT_LEN) is the ciphertext of the first key.
* (MLKEM_SS, ECC_SS_LEN) is the shared secret of the second key.
* (MLKEM_CT, MLKEM_CT_LEN) is the ciphertext of the second key.
* (FIXEDINFO, FIXEDINFO_LEN) is an octet string used to bind the KEK
* to a the key; for PGP we use the concatenation of the session key's
* algorithm id and the v5 fingerprint of the key.
*/
gpg_error_t
gnupg_kem_combiner (void *kek, size_t kek_len,
const void *ecc_ss, size_t ecc_ss_len,
const void *ecc_ct, size_t ecc_ct_len,
const void *mlkem_ss, size_t mlkem_ss_len,
const void *mlkem_ct, size_t mlkem_ct_len,
const void *fixedinfo, size_t fixedinfo_len)
{
gpg_error_t err;
gcry_buffer_t iov[6];
memset (iov, 0, sizeof (iov));
iov[0].data = "\x00\x00\x00\x01"; /* Counter */
iov[0].len = 4;
iov[1].data = (unsigned char *)ecc_ss;
iov[1].len = ecc_ss_len;
iov[2].data = (unsigned char *)ecc_ct;
iov[2].len = ecc_ct_len;
iov[3].data = (unsigned char *)mlkem_ss;
iov[3].len = mlkem_ss_len;
iov[4].data = (unsigned char *)mlkem_ct;
iov[4].len = mlkem_ct_len;
iov[5].data = (unsigned char *)fixedinfo;
iov[5].len = fixedinfo_len;
err = compute_kmac256 (kek, kek_len,
KMAC_KEY, strlen (KMAC_KEY),
KMAC_CUSTOM, strlen (KMAC_CUSTOM), iov, 6);
return err;
}

View File

@ -36,27 +36,6 @@
#include "iobuf.h"
#include "i18n.h"
/* Used by libgcrypt for logging. */
static void
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
{
(void)dummy;
/* Map the log levels. */
switch (level)
{
case GCRY_LOG_CONT: level = GPGRT_LOGLVL_CONT; break;
case GCRY_LOG_INFO: level = GPGRT_LOGLVL_INFO; break;
case GCRY_LOG_WARN: level = GPGRT_LOGLVL_WARN; break;
case GCRY_LOG_ERROR:level = GPGRT_LOGLVL_ERROR; break;
case GCRY_LOG_FATAL:level = GPGRT_LOGLVL_FATAL; break;
case GCRY_LOG_BUG: level = GPGRT_LOGLVL_BUG; break;
case GCRY_LOG_DEBUG:level = GPGRT_LOGLVL_DEBUG; break;
default: level = GPGRT_LOGLVL_ERROR; break;
}
log_logv (level, fmt, arg_ptr);
}
/* This function is called by libgcrypt on a fatal error. */
static void
@ -100,7 +79,6 @@ my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
void
setup_libgcrypt_logging (void)
{
gcry_set_log_handler (my_gcry_logger, NULL);
gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
}
@ -687,3 +665,53 @@ parse_compatibility_flags (const char *string, unsigned int *flagvar,
*flagvar |= result;
return 0;
}
/* Convert STRING consisting of base64 characters into its binary
* representation and store the result in a newly allocated buffer at
* R_BUFFER with its length at R_BUFLEN. If TITLE is NULL a plain
* base64 decoding is done. If it is the empty string the decoder
* will skip everything until a "-----BEGIN " line has been seen,
* decoding then ends at a "----END " line. On failure the function
* returns an error code and sets R_BUFFER to NULL. If the decoded
* data has a length of 0 a dummy buffer will still be allocated and
* the length is set to 0. */
gpg_error_t
b64decode (const char *string, const char *title,
void **r_buffer, size_t *r_buflen)
{
gpg_error_t err;
gpgrt_b64state_t state;
size_t nbytes;
char *buffer;
*r_buffer = NULL;
*r_buflen = 0;
buffer = xtrystrdup (string);
if (!buffer)
return gpg_error_from_syserror();
state = gpgrt_b64dec_start (title);
if (!state)
{
err = gpg_error_from_syserror ();
xfree (buffer);
return err;
}
err = gpgrt_b64dec_proc (state, buffer, strlen (buffer), &nbytes);
if (!err)
{
err = gpgrt_b64dec_finish (state);
state = NULL;
}
if (err)
xfree (buffer);
else
{
*r_buffer = buffer;
*r_buflen = nbytes;
}
gpgrt_b64dec_finish (state); /* Make sure it is released. */
return err;
}

View File

@ -43,23 +43,34 @@ static struct {
const char *oidstr; /* IETF formatted OID. */
unsigned int nbits; /* Nominal bit length of the curve. */
const char *alias; /* NULL or alternative name of the curve. */
const char *abbr; /* NULL or abbreviated name of the curve. */
int pubkey_algo; /* Required OpenPGP algo or 0 for ECDSA/ECDH. */
enum gcry_kem_algos kem_algo; /* 0 or the KEM algorithm for PQC. */
} oidtable[] = {
{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", PUBKEY_ALGO_ECDH },
{ "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519", PUBKEY_ALGO_EDDSA },
{ "Curve25519", "1.3.101.110", 255, "cv25519", PUBKEY_ALGO_ECDH },
{ "Ed25519", "1.3.101.112", 255, "ed25519", PUBKEY_ALGO_EDDSA },
{ "X448", "1.3.101.111", 448, "cv448", PUBKEY_ALGO_ECDH },
{ "Ed448", "1.3.101.113", 456, "ed448", PUBKEY_ALGO_EDDSA },
{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", NULL,
PUBKEY_ALGO_ECDH, GCRY_KEM_RAW_X25519 /* only during development */},
{ "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519", NULL,
PUBKEY_ALGO_EDDSA },
{ "Curve25519", "1.3.101.110", 255, "cv25519", NULL,
PUBKEY_ALGO_ECDH, GCRY_KEM_RAW_X25519 },
{ "Ed25519", "1.3.101.112", 255, "ed25519", NULL,
PUBKEY_ALGO_EDDSA },
{ "X448", "1.3.101.111", 448, "cv448", NULL,
PUBKEY_ALGO_ECDH, GCRY_KEM_RAW_X448 },
{ "Ed448", "1.3.101.113", 456, "ed448", NULL,
PUBKEY_ALGO_EDDSA },
{ "NIST P-256", "1.2.840.10045.3.1.7", 256, "nistp256" },
{ "NIST P-384", "1.3.132.0.34", 384, "nistp384" },
{ "NIST P-521", "1.3.132.0.35", 521, "nistp521" },
{ "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", 256 },
{ "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", 384 },
{ "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", 512 },
{ "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", 256, NULL, "bp256",
0, GCRY_KEM_RAW_BP256 },
{ "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", 384, NULL, "bp384",
0, GCRY_KEM_RAW_BP384 },
{ "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", 512, NULL, "bp512",
0, GCRY_KEM_RAW_BP512 },
{ "secp256k1", "1.3.132.0.10", 256 },
@ -477,10 +488,20 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo)
/* Map an OpenPGP OID to the Libgcrypt curve name. Returns NULL for
* unknown curve names. Unless CANON is set we prefer an alias name
* here which is more suitable for printing. */
* unknown curve names. MODE defines which version of the curve name
* is returned. For example:
*
* | OID | mode=0 | mode=1 | mode=2 |
* |----------------------+-----------------+-----------------+----------|
* | 1.2.840.10045.3.1.7 | nistp256 | NIST P-256 | nistp256 |
* | 1.3.36.3.3.2.8.1.1.7 | brainpoolP256r1 | brainpoolP256r1 | bp256 |
*
* Thus mode 0 returns the name as commonly used gpg, mode 1 returns
* the canonical name, and mode 2 prefers an abbreviated name over the
* commonly used name.
*/
const char *
openpgp_oid_to_curve (const char *oidstr, int canon)
openpgp_oid_to_curve (const char *oidstr, int mode)
{
int i;
@ -489,7 +510,15 @@ openpgp_oid_to_curve (const char *oidstr, int canon)
for (i=0; oidtable[i].name; i++)
if (!strcmp (oidtable[i].oidstr, oidstr))
return !canon && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
{
if (mode == 2)
{
if (oidtable[i].abbr)
return oidtable[i].abbr;
mode = 0; /* No abbreviation - fallback to mode 0. */
}
return !mode && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
}
return NULL;
}
@ -517,6 +546,29 @@ openpgp_oid_or_name_to_curve (const char *oidname, int canon)
}
/* Return the KEM algorithm id for the curve with OIDNAME. */
enum gcry_kem_algos
openpgp_oid_to_kem_algo (const char *oidname)
{
int i;
if (!oidname)
return 0;
for (i=0; oidtable[i].name; i++)
if (!strcmp (oidtable[i].oidstr, oidname))
return oidtable[i].kem_algo;
for (i=0; oidtable[i].name; i++)
if (!ascii_strcasecmp (oidtable[i].name, oidname)
|| (oidtable[i].alias
&& !ascii_strcasecmp (oidtable[i].alias, oidname)))
return oidtable[i].kem_algo;
return 0;
}
/* Return true if the curve with NAME is supported. */
static int
curve_supported_p (const char *name)
@ -574,7 +626,9 @@ openpgp_is_curve_supported (const char *name, int *r_algo,
{
if ((!ascii_strcasecmp (name, oidtable[idx].name)
|| (oidtable[idx].alias
&& !ascii_strcasecmp (name, (oidtable[idx].alias))))
&& !ascii_strcasecmp (name, (oidtable[idx].alias)))
|| (oidtable[idx].abbr
&& !ascii_strcasecmp (name, (oidtable[idx].abbr))))
&& curve_supported_p (oidtable[idx].name))
{
if (r_algo)
@ -598,6 +652,7 @@ map_gcry_pk_to_openpgp (enum gcry_pk_algos algo)
case GCRY_PK_EDDSA: return PUBKEY_ALGO_EDDSA;
case GCRY_PK_ECDSA: return PUBKEY_ALGO_ECDSA;
case GCRY_PK_ECDH: return PUBKEY_ALGO_ECDH;
case GCRY_PK_KEM: return PUBKEY_ALGO_KYBER;
default: return algo < 110 ? (pubkey_algo_t)algo : 0;
}
}

View File

@ -171,7 +171,11 @@ typedef enum
PUBKEY_ALGO_ECDSA = 19, /* RFC-6637 */
PUBKEY_ALGO_ELGAMAL = 20, /* Elgamal encrypt+sign (legacy). */
/* 21 reserved by OpenPGP. */
PUBKEY_ALGO_EDDSA = 22, /* EdDSA (not yet assigned). */
PUBKEY_ALGO_EDDSA = 22, /* EdDSA. */
PUBKEY_ALGO_KYBER = 29, /* Kyber */
PUBKEY_ALGO_DIL3_25519 = 35, /* Dilithium3 + Ed25519 (aka ML-DSA-65) */
PUBKEY_ALGO_DIL5_448 = 36, /* Dilithium5 + Ed448 (aka ML-DSA-87) */
PUBKEY_ALGO_SPHINX_SHA2 = 41, /* SPHINX+-simple-SHA2 (aka SLH-DSA-SHA2) */
PUBKEY_ALGO_PRIVATE10 = 110
}
pubkey_algo_t;
@ -206,7 +210,7 @@ compress_algo_t;
#define OPENPGP_MAX_NPKEY 5 /* Maximum number of public key parameters. */
#define OPENPGP_MAX_NSKEY 7 /* Maximum number of secret key parameters. */
#define OPENPGP_MAX_NSIG 2 /* Maximum number of signature parameters. */
#define OPENPGP_MAX_NENC 2 /* Maximum number of encryption parameters. */
#define OPENPGP_MAX_NENC 4 /* Maximum number of encryption parameters. */
/* Decode an rfc4880 encoded S2K count. */

View File

@ -992,7 +992,7 @@ get_pk_algo_from_key (gcry_sexp_t key)
gcry_sexp_t list;
const char *s;
size_t n;
char algoname[6];
char algoname[10];
int algo = 0;
list = gcry_sexp_nth (key, 1);
@ -1194,3 +1194,47 @@ cipher_mode_to_string (int mode)
default: return "[?]";
}
}
/* Return the cannonical name of the ECC curve in KEY. */
const char *
get_ecc_curve_from_key (gcry_sexp_t key)
{
gcry_sexp_t list = NULL;
gcry_sexp_t l2 = NULL;
const char *curve_name = NULL;
char *name = NULL;
/* Check that the first element is valid. */
list = gcry_sexp_find_token (key, "public-key", 0);
if (!list)
list = gcry_sexp_find_token (key, "private-key", 0);
if (!list)
list = gcry_sexp_find_token (key, "protected-private-key", 0);
if (!list)
list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
if (!list)
goto leave;
l2 = gcry_sexp_cadr (list);
gcry_sexp_release (list);
list = l2;
l2 = NULL;
name = gcry_sexp_nth_string (list, 0);
if (!name)
goto leave;
if (gcry_pk_map_name (name) != GCRY_PK_ECC)
goto leave;
l2 = gcry_sexp_find_token (list, "curve", 0);
xfree (name);
name = gcry_sexp_nth_string (l2, 1);
curve_name = openpgp_oid_or_name_to_curve (name, 1);
gcry_sexp_release (l2);
leave:
xfree (name);
gcry_sexp_release (list);
return curve_name;
}

View File

@ -259,7 +259,7 @@ get_fingerprint (gcry_sexp_t key, int algo,
}
else
{
struct b64state b64s;
gpgrt_b64state_t b64s;
estream_t stream;
char *p;
long int len;
@ -273,15 +273,15 @@ get_fingerprint (gcry_sexp_t key, int algo,
goto leave;
}
err = b64enc_start_es (&b64s, stream, "");
if (err)
b64s = gpgrt_b64enc_start (stream, "");
if (!b64s)
{
es_fclose (stream);
goto leave;
}
err = b64enc_write (&b64s,
gcry_md_read (md, algo), gcry_md_get_algo_dlen (algo));
err = gpgrt_b64enc_write (b64s, gcry_md_read (md, algo),
gcry_md_get_algo_dlen (algo));
if (err)
{
es_fclose (stream);
@ -289,7 +289,7 @@ get_fingerprint (gcry_sexp_t key, int algo,
}
/* Finish, get the length, and close the stream. */
err = b64enc_finish (&b64s);
err = gpgrt_b64enc_finish (b64s);
len = es_ftell (stream);
es_fclose (stream);
if (err)
@ -566,7 +566,7 @@ ssh_public_key_in_base64 (gcry_sexp_t key, estream_t stream,
const char *identifier = NULL;
void *blob = NULL;
size_t bloblen;
struct b64state b64_state;
gpgrt_b64state_t b64_state;
algo = get_pk_algo_from_key (key);
if (algo == 0)
@ -624,15 +624,15 @@ ssh_public_key_in_base64 (gcry_sexp_t key, estream_t stream,
es_fprintf (stream, "%s ", identifier);
err = b64enc_start_es (&b64_state, stream, "");
if (err)
b64_state = gpgrt_b64enc_start (stream, "");
if (!b64_state)
{
es_free (blob);
return err;
return gpg_error_from_syserror ();
}
err = b64enc_write (&b64_state, blob, bloblen);
b64enc_finish (&b64_state);
err = gpgrt_b64enc_write (b64_state, blob, bloblen);
gpgrt_b64enc_finish (b64_state);
es_free (blob);
if (err)
return err;

View File

@ -54,6 +54,7 @@ enum
STATUS_NEED_PASSPHRASE,
STATUS_VALIDSIG,
STATUS_ASSERT_SIGNER,
STATUS_ASSERT_PUBKEY_ALGO,
STATUS_SIG_ID,
STATUS_ENC_TO,
STATUS_NODATA,

View File

@ -113,6 +113,8 @@ static int allow_special_filenames;
#ifdef HAVE_W32_SYSTEM
/* State of gnupg_inhibit_set_foregound_window. */
static int inhibit_set_foregound_window;
/* Disable the use of _open_osfhandle. */
static int no_translate_sys2libc_fd;
#endif
@ -351,6 +353,16 @@ enable_special_filenames (void)
}
/* Disable the use use of _open_osfhandle on Windows. */
void
disable_translate_sys2libc_fd (void)
{
#ifdef HAVE_W32_SYSTEM
no_translate_sys2libc_fd = 1;
#endif
}
/* Return a string which is used as a kind of process ID. */
const byte *
get_session_marker (size_t *rlen)
@ -537,10 +549,10 @@ gnupg_usleep (unsigned int usecs)
different from the libc file descriptors (like open). This function
translates system file handles to libc file handles. FOR_WRITE
gives the direction of the handle. */
int
#if defined(HAVE_W32_SYSTEM)
static int
translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
{
#if defined(HAVE_W32_SYSTEM)
int x;
if (fd == GNUPG_INVALID_FD)
@ -552,27 +564,87 @@ translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
if (x == -1)
log_error ("failed to translate osfhandle %p\n", (void *) fd);
return x;
#else /*!HAVE_W32_SYSTEM */
}
#endif /*!HAVE_W32_SYSTEM */
/* This is the same as translate_sys2libc_fd but takes an integer
which is assumed to be such an system handle. */
int
translate_sys2libc_fd_int (int fd, int for_write)
{
#ifdef HAVE_W32_SYSTEM
if (fd <= 2 || no_translate_sys2libc_fd)
return fd; /* Do not do this for stdin, stdout, and stderr. */
return translate_sys2libc_fd ((void*)(intptr_t)fd, for_write);
#else
(void)for_write;
return fd;
#endif
}
/* This is the same as translate_sys2libc_fd but takes an integer
which is assumed to be such an system handle. On WindowsCE the
passed FD is a rendezvous ID and the function finishes the pipe
creation. */
int
translate_sys2libc_fd_int (int fd, int for_write)
{
#ifdef HAVE_W32_SYSTEM
if (fd <= 2)
return fd; /* Do not do this for error, stdin, stdout, stderr. */
return translate_sys2libc_fd ((void*)fd, for_write);
/*
* Parse the string representation of a file reference (file handle on
* Windows or file descriptor on POSIX) in FDSTR. The string
* representation may be either of folllowing:
* (1) 0, 1, or 2 which means stdin, stdout, and stderr, respectively.
* (2) Integer representation (by %d of printf).
* (3) Hex representation which starts as "0x".
*
* Then, fill R_SYSHD, according to the value of a file reference.
*
*/
gpg_error_t
gnupg_parse_fdstr (const char *fdstr, es_syshd_t *r_syshd)
{
int fd = -1;
#ifdef HAVE_W32_SYSTEM
gnupg_fd_t hd;
char *endptr;
int base;
if (!strcmp (fdstr, "0"))
fd = 0;
else if (!strcmp (fdstr, "1"))
fd = 1;
else if (!strcmp (fdstr, "2"))
fd = 2;
if (fd >= 0)
{
r_syshd->type = ES_SYSHD_FD;
r_syshd->u.fd = fd;
return 0;
}
if (!strncmp (fdstr, "0x", 2))
{
base = 16;
fdstr += 2;
}
else
base = 10;
gpg_err_set_errno (0);
#ifdef _WIN64
hd = (gnupg_fd_t)strtoll (fdstr, &endptr, base);
#else
(void)for_write;
return fd;
hd = (gnupg_fd_t)strtol (fdstr, &endptr, base);
#endif
if (errno != 0 || endptr == fdstr || *endptr != '\0')
return gpg_error (GPG_ERR_INV_ARG);
r_syshd->type = ES_SYSHD_HANDLE;
r_syshd->u.handle = hd;
return 0;
#else
fd = atoi (fdstr);
r_syshd->type = ES_SYSHD_FD;
r_syshd->u.fd = fd;
return 0;
#endif
}
@ -594,13 +666,74 @@ check_special_filename (const char *fname, int for_write, int notranslate)
for (i=0; digitp (fname+i); i++ )
;
if (!fname[i])
return notranslate? atoi (fname)
/**/ : translate_sys2libc_fd_int (atoi (fname), for_write);
{
if (notranslate)
return atoi (fname);
else
{
es_syshd_t syshd;
if (gnupg_parse_fdstr (fname, &syshd))
return -1;
#ifdef HAVE_W32_SYSTEM
if (syshd.type == ES_SYSHD_FD)
return syshd.u.fd;
else
return translate_sys2libc_fd ((gnupg_fd_t)syshd.u.handle, for_write);
#else
(void)for_write;
return syshd.u.fd;
#endif
}
}
}
return -1;
}
/* Check whether FNAME has the form "-&nnnn", where N is a number
* representing a file. Returns GNUPG_INVALID_FD if it is not the
* case. Returns a file descriptor on POSIX, a system handle on
* Windows. */
gnupg_fd_t
gnupg_check_special_filename (const char *fname)
{
if (allow_special_filenames
&& fname && *fname == '-' && fname[1] == '&')
{
int i;
fname += 2;
for (i=0; digitp (fname+i); i++ )
;
if (!fname[i])
{
es_syshd_t syshd;
if (gnupg_parse_fdstr (fname, &syshd))
return GNUPG_INVALID_FD;
#ifdef HAVE_W32_SYSTEM
if (syshd.type == ES_SYSHD_FD)
{
if (syshd.u.fd == 0)
return GetStdHandle (STD_INPUT_HANDLE);
else if (syshd.u.fd == 1)
return GetStdHandle (STD_OUTPUT_HANDLE);
else if (syshd.u.fd == 2)
return GetStdHandle (STD_ERROR_HANDLE);
}
else
return syshd.u.handle;
#else
return syshd.u.fd;
#endif
}
}
return GNUPG_INVALID_FD;
}
/* Replacement for tmpfile(). This is required because the tmpfile
function of Windows' runtime library is broken, insecure, ignores
TMPDIR and so on. In addition we create a file with an inheritable
@ -1158,6 +1291,19 @@ gnupg_setenv (const char *name, const char *value, int overwrite)
return setenv (name, value, overwrite);
#else /*!HAVE_SETENV*/
if (! getenv (name) || overwrite)
#if defined(HAVE_W32_SYSTEM) && defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
{
int e = _putenv_s (name, value);
if (e)
{
gpg_err_set_errno (e);
return -1;
}
else
return 0;
}
#else
{
char *buf;
@ -1175,6 +1321,7 @@ gnupg_setenv (const char *name, const char *value, int overwrite)
# endif
return putenv (buf);
}
#endif /*!HAVE_W32_SYSTEM*/
return 0;
#endif /*!HAVE_SETENV*/
}
@ -1199,6 +1346,18 @@ gnupg_unsetenv (const char *name)
#ifdef HAVE_UNSETENV
return unsetenv (name);
#elif defined(HAVE_W32_SYSTEM) && defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
{
int e = _putenv_s (name, "");
if (e)
{
gpg_err_set_errno (e);
return -1;
}
else
return 0;
}
#else /*!HAVE_UNSETENV*/
{
char *buf;
@ -1829,3 +1988,22 @@ gnupg_fd_valid (int fd)
close (d);
return 1;
}
/* Open a stream from FD (a file descriptor on POSIX, a system
handle on Windows), non-closed. */
estream_t
open_stream_nc (gnupg_fd_t fd, const char *mode)
{
es_syshd_t syshd;
#ifdef HAVE_W32_SYSTEM
syshd.type = ES_SYSHD_HANDLE;
syshd.u.handle = fd;
#else
syshd.type = ES_SYSHD_FD;
syshd.u.fd = fd;
#endif
return es_sysopen_nc (&syshd, mode);
}

View File

@ -38,12 +38,20 @@
typedef void *gnupg_fd_t;
#define GNUPG_INVALID_FD ((void*)(-1))
#define INT2FD(s) ((void *)(s))
#define FD2INT(h) ((unsigned int)(h))
# ifdef _WIN64
# define FD2INT(h) ((intptr_t)(h))
# else
# define FD2INT(h) ((unsigned int)(h))
# endif
#define FD_DBG(h) ((int)(intptr_t)(h))
#define FD2NUM(h) ((int)(intptr_t)(h))
#else
typedef int gnupg_fd_t;
#define GNUPG_INVALID_FD (-1)
#define INT2FD(s) (s)
#define FD2INT(h) (h)
#define FD_DBG(h) (h)
#define FD2NUM(h) (h)
#endif
#ifdef HAVE_STAT
@ -67,14 +75,17 @@ void trap_unaligned (void);
int disable_core_dumps (void);
int enable_core_dumps (void);
void enable_special_filenames (void);
void disable_translate_sys2libc_fd (void);
const unsigned char *get_session_marker (size_t *rlen);
unsigned int get_uint_nonce (void);
/*int check_permissions (const char *path,int extension,int checkonly);*/
void gnupg_sleep (unsigned int seconds);
void gnupg_usleep (unsigned int usecs);
int translate_sys2libc_fd (gnupg_fd_t fd, int for_write);
int translate_sys2libc_fd_int (int fd, int for_write);
gpg_error_t gnupg_parse_fdstr (const char *fdstr, es_syshd_t *r_syshd);
int check_special_filename (const char *fname, int for_write, int notranslate);
gnupg_fd_t gnupg_check_special_filename (const char *fname);
FILE *gnupg_tmpfile (void);
void gnupg_reopen_std (const char *pgmname);
void gnupg_inhibit_set_foregound_window (int yes);
@ -108,6 +119,7 @@ gpg_error_t gnupg_inotify_watch_delete_self (int *r_fd, const char *fname);
gpg_error_t gnupg_inotify_watch_socket (int *r_fd, const char *socket_name);
int gnupg_inotify_has_name (int fd, const char *name);
estream_t open_stream_nc (gnupg_fd_t fd, const char *mode);
#ifdef HAVE_W32_SYSTEM
int gnupg_w32_set_errno (int ec);

View File

@ -1,283 +0,0 @@
/* t-b64.c - Module tests for b64enc.c and b64dec.c
* Copyright (C) 2008 Free Software Foundation, Inc.
* Copyright (C) 2008, 2023 g10 Code GmbH
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "util.h"
#define pass() do { ; } while(0)
#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
__FILE__,__LINE__, (a)); \
errcount++; \
} while(0)
#define oops() do { fprintf (stderr, "%s:%d: ooops\n", \
__FILE__,__LINE__); \
exit (2); \
} while(0)
static int verbose;
static int errcount;
/* Convert STRING consisting of hex characters into its binary
* representation and return it as an allocated buffer. The valid
* length of the buffer is returned at R_LENGTH. The string is
* delimited by end of string. The function returns NULL on
* error. */
static void *
hex2buffer (const char *string, size_t *r_length)
{
const char *s;
unsigned char *buffer;
size_t length;
buffer = xmalloc (strlen(string)/2+1);
length = 0;
for (s=string; *s; s +=2 )
{
if (!hexdigitp (s) || !hexdigitp (s+1))
return NULL; /* Invalid hex digits. */
((unsigned char*)buffer)[length++] = xtoi_2 (s);
}
*r_length = length;
return buffer;
}
static void
test_b64decode (void)
{
static struct {
const char *string; /* String to test. */
const char *title; /* title parameter. */
gpg_error_t err; /* expected error. */
const char *datastr; /* Expected data (hex encoded) */
} tests[] = {
{ "YQ==", NULL, 0,
"61" },
{ "YWE==", NULL, 0,
"6161" },
{ "YWFh", NULL, 0,
"616161" },
{ "YWFhYQ==", NULL, 0,
"61616161" },
{ "YWJjZA==", NULL, 0,
"61626364" },
{ "AA=", NULL, 0,
"00" },
{ "AAEA=", NULL, 0,
"000100" },
{ "/w==", NULL, 0,
"ff" },
{ "oRQwEqADCgEDoQsGCSqGSIL3EgECAg==", NULL, 0,
"a1143012a0030a0103a10b06092a864882f712010202" },
{ "oRQwEqADCgEDoQsGCSqGSIL3EgECA-==", NULL, GPG_ERR_BAD_DATA,
"a1143012a0030a0103a10b06092a864882f712010202" },
{ "oRQwEqADCgEDoQsGCSqGSIL3EgECAg==", "", 0,
"" },
{ "-----BEGIN PGP\n\n"
"oRQwEqADCgEDoQsGCSqGSIL3EgECAg==\n"
"-----END PGP\n", "", 0,
"a1143012a0030a0103a10b06092a864882f712010202" },
{ "", NULL, 0,
"" }
};
int tidx;
gpg_error_t err;
void *data = NULL;
size_t datalen;
char *wantdata = NULL;
size_t wantdatalen;
for (tidx = 0; tidx < DIM(tests); tidx++)
{
xfree (wantdata);
if (!(wantdata = hex2buffer (tests[tidx].datastr, &wantdatalen)))
oops ();
xfree (data);
err = b64decode (tests[tidx].string, tests[tidx].title, &data, &datalen);
if (verbose)
fprintf (stderr, "%s:%d: test %d, err=%d, datalen=%zu\n",
__FILE__, __LINE__, tidx, err, datalen);
if (gpg_err_code (err) != tests[tidx].err)
fail (tidx);
else if (err)
pass ();
else if (wantdatalen != datalen)
fail (tidx);
else if (memcmp (wantdata, data, datalen))
fail (tidx);
else
pass ();
}
xfree (wantdata);
xfree (data);
}
static void
test_b64enc_pgp (const char *string)
{
gpg_error_t err;
struct b64state state;
if (!string)
string = "a";
err = b64enc_start (&state, stdout, "PGP MESSAGE");
if (err)
fail (1);
err = b64enc_write (&state, string, strlen (string));
if (err)
fail (2);
err = b64enc_finish (&state);
if (err)
fail (3);
pass ();
}
static void
test_b64enc_file (const char *fname)
{
gpg_error_t err;
struct b64state state;
FILE *fp;
char buffer[50];
size_t nread;
fp = fname ? fopen (fname, "r") : stdin;
if (!fp)
{
fprintf (stderr, "%s:%d: can't open '%s': %s\n",
__FILE__, __LINE__, fname? fname:"[stdin]", strerror (errno));
fail (0);
}
err = b64enc_start (&state, stdout, "DATA");
if (err)
fail (1);
while ( (nread = fread (buffer, 1, sizeof buffer, fp)) )
{
err = b64enc_write (&state, buffer, nread);
if (err)
fail (2);
}
err = b64enc_finish (&state);
if (err)
fail (3);
fclose (fp);
pass ();
}
static void
test_b64dec_file (const char *fname)
{
gpg_error_t err;
struct b64state state;
FILE *fp;
char buffer[50];
size_t nread, nbytes;
fp = fname ? fopen (fname, "r") : stdin;
if (!fp)
{
fprintf (stderr, "%s:%d: can't open '%s': %s\n",
__FILE__, __LINE__, fname? fname:"[stdin]", strerror (errno));
fail (0);
}
err = b64dec_start (&state, "");
if (err)
fail (1);
while ( (nread = fread (buffer, 1, sizeof buffer, fp)) )
{
err = b64dec_proc (&state, buffer, nread, &nbytes);
if (err)
{
if (gpg_err_code (err) == GPG_ERR_EOF)
break;
fail (2);
}
else if (nbytes)
fwrite (buffer, 1, nbytes, stdout);
}
err = b64dec_finish (&state);
if (err)
fail (3);
fclose (fp);
pass ();
}
int
main (int argc, char **argv)
{
int do_encode = 0;
int do_decode = 0;
int do_pgpdecode = 0;
if (argc)
{ argc--; argv++; }
if (argc && !strcmp (argv[0], "--verbose"))
{
verbose = 1;
argc--; argv++;
}
if (argc && !strcmp (argv[0], "--encode"))
{
do_encode = 1;
argc--; argv++;
}
else if (argc && !strcmp (argv[0], "--decode"))
{
do_decode = 1;
argc--; argv++;
}
else if (argc)
do_pgpdecode = 1;
if (do_encode)
test_b64enc_file (argc? *argv: NULL);
else if (do_decode)
test_b64dec_file (argc? *argv: NULL);
else if (do_pgpdecode)
test_b64enc_pgp (argc? *argv: NULL);
else
test_b64decode ();
return !!errcount;
}

View File

@ -29,7 +29,7 @@
static int verbose;
#ifndef HAVE_W32_SYSTEM
static void
print_open_fds (int *array)
{
@ -169,20 +169,168 @@ test_close_all_fds (void)
}
}
#endif
static char buff12k[1024*12];
static char buff4k[1024*4];
static void
run_server (void)
{
estream_t fp;
int i;
char *p;
unsigned int len;
int ret;
es_syshd_t syshd;
size_t n;
off_t o;
#ifdef HAVE_W32_SYSTEM
syshd.type = ES_SYSHD_HANDLE;
syshd.u.handle = (HANDLE)_get_osfhandle (1);
#else
syshd.type = ES_SYSHD_FD;
syshd.u.fd = 1;
#endif
fp = es_sysopen_nc (&syshd, "w");
if (fp == NULL)
{
fprintf (stderr, "es_fdopen failed\n");
exit (1);
}
/* Fill the buffer by ASCII chars. */
p = buff12k;
for (i = 0; i < sizeof (buff12k); i++)
if ((i % 64) == 63)
*p++ = '\n';
else
*p++ = (i % 64) + '@';
len = sizeof (buff12k);
ret = es_write (fp, (void *)&len, sizeof (len), NULL);
if (ret)
{
fprintf (stderr, "es_write (1) failed\n");
exit (1);
}
es_fflush (fp);
o = 0;
n = len;
while (1)
{
size_t n0, n1;
n0 = n > 4096 ? 4096 : n;
memcpy (buff4k, buff12k + o, n0);
ret = es_write (fp, buff4k, n0, &n1);
if (ret || n0 != n1)
{
fprintf (stderr, "es_write (2) failed\n");
exit (1);
}
o += n0;
n -= n0;
if (n == 0)
break;
}
es_fclose (fp);
exit (0);
}
static void
test_pipe_stream (const char *pgmname)
{
gpg_error_t err;
gnupg_process_t proc;
estream_t outfp;
const char *argv[2];
unsigned int len;
size_t n;
off_t o;
int ret;
argv[0] = "--server";
argv[1] = NULL;
err = gnupg_process_spawn (pgmname, argv,
(GNUPG_PROCESS_STDOUT_PIPE
|GNUPG_PROCESS_STDERR_KEEP),
NULL, NULL, &proc);
if (err)
{
fprintf (stderr, "gnupg_process_spawn failed\n");
exit (1);
}
gnupg_process_get_streams (proc, 0, NULL, &outfp, NULL);
ret = es_read (outfp, (void *)&len, sizeof (len), NULL);
if (ret)
{
fprintf (stderr, "es_read (1) failed\n");
exit (1);
}
o = 0;
while (1)
{
if (es_feof (outfp))
break;
ret = es_read (outfp, buff4k, sizeof (buff4k), &n);
if (ret)
{
fprintf (stderr, "es_read (2) failed\n");
exit (1);
}
memcpy (buff12k + o, buff4k, n);
o += n;
}
if (o != sizeof (buff12k))
{
fprintf (stderr, "received data with wrong length %d\n", (int)o);
exit (1);
}
es_fclose (outfp);
gnupg_process_release (proc);
}
int
main (int argc, char **argv)
{
const char *myname = "no-pgm";
if (argc)
{ argc--; argv++; }
{
myname = argv[0];
argc--; argv++;
}
if (argc && !strcmp (argv[0], "--verbose"))
{
verbose = 1;
argc--; argv++;
}
if (argc && !strcmp (argv[0], "--server"))
run_server ();
#ifndef HAVE_W32_SYSTEM
test_close_all_fds ();
#endif
test_pipe_stream (myname);
return 0;
}

View File

@ -1,3 +1,36 @@
/* t-iobuf.c - Simple module test for iobuf.c
* Copyright (C) 2015 g10 Code GmbH
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later)
*/
/* The whole code here does not very fill into our general test frame
* work patter. But let's keep it as it is. */
#include <config.h>
#include <stdio.h>
#include <string.h>
@ -7,6 +40,20 @@
#include "iobuf.h"
#include "stringhelp.h"
static void *
xmalloc (size_t n)
{
void *p = malloc (n);
if (!p)
{
fprintf (stderr, "t-iobuf: out of core\n");
abort ();
}
return p;
}
/* Return every other byte. In particular, reads two bytes, returns
the second one. */
static int
@ -86,7 +133,7 @@ static struct content_filter_state *
content_filter_new (const char *buffer)
{
struct content_filter_state *state
= malloc (sizeof (struct content_filter_state));
= xmalloc (sizeof (struct content_filter_state));
state->pos = 0;
state->len = strlen (buffer);
@ -215,8 +262,7 @@ main (int argc, char *argv[])
allocate a buffer that is 5 bytes long, then no reallocation
should be required. */
size = 5;
buffer = malloc (size);
assert (buffer);
buffer = xmalloc (size);
max_len = 100;
n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
assert (n == 4);
@ -229,7 +275,7 @@ main (int argc, char *argv[])
requires 6 bytes of storage. We pass a buffer that is 5 bytes
large and we allow the buffer to be grown. */
size = 5;
buffer = malloc (size);
buffer = xmalloc (size);
max_len = 100;
n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
assert (n == 5);
@ -243,7 +289,7 @@ main (int argc, char *argv[])
requires 7 bytes of storage. We pass a buffer that is 5 bytes
large and we don't allow the buffer to be grown. */
size = 5;
buffer = malloc (size);
buffer = xmalloc (size);
max_len = 5;
n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
assert (n == 4);

View File

@ -31,6 +31,8 @@
#ifndef GNUPG_COMMON_T_SUPPORT_H
#define GNUPG_COMMON_T_SUPPORT_H 1
#ifndef LEAN_T_SUPPORT
#ifdef GCRYPT_VERSION
#error The regression tests should not include with gcrypt.h
#endif
@ -45,11 +47,6 @@
# define getenv(a) (NULL)
#endif
#ifndef DIM
# define DIM(v) (sizeof(v)/sizeof((v)[0]))
# define DIMof(type,member) DIM(((type *)0)->member)
#endif
/* Replacement prototypes. */
void *gcry_xmalloc (size_t n);
@ -65,6 +62,12 @@ void gcry_free (void *a);
#define xstrdup(a) gcry_xstrdup ( (a) )
#define xfree(a) gcry_free ( (a) )
#endif /* LEAN_T_SUPPORT */
#ifndef DIM
# define DIM(v) (sizeof(v)/sizeof((v)[0]))
# define DIMof(type,member) DIM(((type *)0)->member)
#endif
/* Macros to print the result of a test. */
#define pass() do { ; } while(0)

View File

@ -152,7 +152,7 @@ find_tlv_unchecked (const unsigned char *buffer, size_t length,
/* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag
* and the length part from the TLV triplet. Update BUFFER and SIZE
* on success. Note that this function does not check that the value
* fits into the provided buffer; this allows to work on the TL part
* fits into the provided buffer; this allows one to work on the TL part
* of a TLV. */
gpg_error_t
parse_ber_header (unsigned char const **buffer, size_t *size,

View File

@ -149,36 +149,6 @@ ssize_t read_line (FILE *fp,
size_t *max_length);
/*-- b64enc.c and b64dec.c --*/
struct b64state
{
unsigned int flags;
int idx;
int quad_count;
FILE *fp;
estream_t stream;
char *title;
unsigned char radbuf[4];
u32 crc;
int stop_seen:1;
int invalid_encoding:1;
gpg_error_t lasterr;
};
gpg_error_t b64enc_start (struct b64state *state, FILE *fp, const char *title);
gpg_error_t b64enc_start_es (struct b64state *state, estream_t fp,
const char *title);
gpg_error_t b64enc_write (struct b64state *state,
const void *buffer, size_t nbytes);
gpg_error_t b64enc_finish (struct b64state *state);
gpg_error_t b64dec_start (struct b64state *state, const char *title);
gpg_error_t b64dec_proc (struct b64state *state, void *buffer, size_t length,
size_t *r_nbytes);
gpg_error_t b64dec_finish (struct b64state *state);
gpg_error_t b64decode (const char *string, const char *title,
void **r_buffer, size_t *r_buflen);
/*-- sexputil.c */
char *canon_sexp_to_string (const unsigned char *canon, size_t canonlen);
void log_printcanon (const char *text,
@ -226,6 +196,7 @@ 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);
const char *cipher_mode_to_string (int mode);
const char *get_ecc_curve_from_key (gcry_sexp_t key);
/*-- convert.c --*/
int hex2bin (const char *string, void *buffer, size_t length);
@ -257,9 +228,10 @@ int openpgp_oidbuf_is_cv25519 (const void *buf, size_t len);
int openpgp_oid_is_cv25519 (gcry_mpi_t a);
int openpgp_oid_is_cv448 (gcry_mpi_t a);
int openpgp_oid_is_ed448 (gcry_mpi_t a);
enum gcry_kem_algos openpgp_oid_to_kem_algo (const char *oidname);
const char *openpgp_curve_to_oid (const char *name,
unsigned int *r_nbits, int *r_algo);
const char *openpgp_oid_to_curve (const char *oid, int canon);
const char *openpgp_oid_to_curve (const char *oid, int mode);
const char *openpgp_oid_or_name_to_curve (const char *oidname, int canon);
const char *openpgp_enum_curves (int *idxp);
const char *openpgp_is_curve_supported (const char *name,
@ -274,6 +246,7 @@ void gnupg_set_homedir (const char *newdir);
void gnupg_maybe_make_homedir (const char *fname, int quiet);
const char *gnupg_homedir (void);
int gnupg_default_homedir_p (void);
const char *gnupg_registry_dir (void);
const char *gnupg_daemon_rootdir (void);
const char *gnupg_socketdir (void);
const char *gnupg_sysconfdir (void);
@ -328,6 +301,19 @@ char *gnupg_get_help_string (const char *key, int only_current_locale);
/*-- localename.c --*/
const char *gnupg_messages_locale_name (void);
/*-- kem.c --*/
gpg_error_t gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
int hashalgo, const void *ecdh, size_t ecdh_len,
const void *ecc_ct, size_t ecc_ct_len,
const void *ecc_pk, size_t ecc_pk_len);
gpg_error_t gnupg_kem_combiner (void *kek, size_t kek_len,
const void *ecc_ss, size_t ecc_ss_len,
const void *ecc_ct, size_t ecc_ct_len,
const void *mlkem_ss, size_t mlkem_ss_len,
const void *mlkem_ct, size_t mlkem_ct_len,
const void *fixedinfo, size_t fixedinfo_len);
/*-- miscellaneous.c --*/
/* This function is called at startup to tell libgcrypt to use our own
@ -388,6 +374,10 @@ struct compatibility_flags_s
int parse_compatibility_flags (const char *string, unsigned int *flagvar,
const struct compatibility_flags_s *flags);
gpg_error_t b64decode (const char *string, const char *title,
void **r_buffer, size_t *r_buflen);
/*-- Simple replacement functions. */

View File

@ -28,8 +28,8 @@ min_automake_version="1.16.3"
# another commit and push so that the git magic is able to work.
m4_define([mym4_package],[gnupg])
m4_define([mym4_major], [2])
m4_define([mym4_minor], [4])
m4_define([mym4_micro], [4])
m4_define([mym4_minor], [5])
m4_define([mym4_micro], [0])
# 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
@ -53,15 +53,15 @@ AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
# When changing the SWDB tag please also adjust the hard coded tags in
# build-aux/speedo.mk, build-aux/getswdb.sh, and Makefile.am
# As well as the source info for the man pages.
AC_DEFINE_UNQUOTED(GNUPG_SWDB_TAG, "gnupg24", [swdb tag for this branch])
AC_DEFINE_UNQUOTED(GNUPG_SWDB_TAG, "gnupg26", [swdb tag for this branch])
NEED_GPGRT_VERSION=1.46
NEED_LIBGCRYPT_API=1
NEED_LIBGCRYPT_VERSION=1.9.1
NEED_LIBGCRYPT_VERSION=1.11.0
NEED_LIBASSUAN_API=2
NEED_LIBASSUAN_VERSION=2.5.0
NEED_LIBASSUAN_API=3
NEED_LIBASSUAN_VERSION=3.0.0
NEED_KSBA_API=1
NEED_KSBA_VERSION=1.6.3
@ -1385,6 +1385,8 @@ AC_CHECK_SIZEOF(time_t,,[[
]])
GNUPG_TIME_T_UNSIGNED
# Check SOCKET type for Windows.
AC_CHECK_TYPES([SOCKET], [], [], [[#include "winsock2.h"]])
if test "$ac_cv_sizeof_unsigned_short" = "0" \
|| test "$ac_cv_sizeof_unsigned_int" = "0" \

View File

@ -100,7 +100,8 @@ static unsigned int any_cert_of_class;
#ifdef HAVE_W32_SYSTEM
/* We load some functions dynamically. Provide typedefs for tehse
#include <wincrypt.h>
/* We load some functions dynamically. Provide typedefs for these
* functions. */
typedef HCERTSTORE (WINAPI *CERTOPENSYSTEMSTORE)
(HCRYPTPROV hProv, LPCSTR szSubsystemProtocol);

View File

@ -2086,6 +2086,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
err = validate_cert_chain (ctrl, crlissuer_cert, NULL,
(VALIDATE_FLAG_TRUST_CONFIG
| VALIDATE_FLAG_TRUST_SYSTEM
| VALIDATE_FLAG_CRL
| VALIDATE_FLAG_RECURSIVE),
r_trust_anchor);

View File

@ -39,10 +39,10 @@
2008) we need a context in the reader callback. */
struct reader_cb_context_s
{
estream_t fp; /* The stream used with the ksba reader. */
int checked:1; /* PEM/binary detection ahs been done. */
int is_pem:1; /* The file stream is PEM encoded. */
struct b64state b64state; /* The state used for Base64 decoding. */
estream_t fp; /* The stream used with the ksba reader. */
unsigned int checked:1; /* PEM/binary detection ahs been done. */
unsigned int is_pem:1; /* The file stream is PEM encoded. */
gpgrt_b64state_t b64state; /* The state used for Base64 decoding. */
};
@ -126,14 +126,16 @@ my_es_read (void *opaque, char *buffer, size_t nbytes, size_t *nread)
else
{
cb_ctx->is_pem = 1;
b64dec_start (&cb_ctx->b64state, "");
cb_ctx->b64state = gpgrt_b64dec_start ("");
if (!cb_ctx->b64state)
return gpg_error_from_syserror ();
}
}
if (cb_ctx->is_pem && *nread)
{
size_t nread2;
if (b64dec_proc (&cb_ctx->b64state, buffer, *nread, &nread2))
if (gpgrt_b64dec_proc (cb_ctx->b64state, buffer, *nread, &nread2))
{
/* EOF from decoder. */
*nread = 0;
@ -581,7 +583,7 @@ crl_close_reader (ksba_reader_t reader)
es_fclose (cb_ctx->fp);
/* Release the base64 decoder state. */
if (cb_ctx->is_pem)
b64dec_finish (&cb_ctx->b64state);
gpgrt_b64dec_finish (cb_ctx->b64state);
/* Release the callback context. */
xfree (cb_ctx);
}

View File

@ -308,7 +308,7 @@ main (int argc, char **argv )
opt.dirmngr_program
? opt.dirmngr_program
: gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR),
! cmd_ping,
cmd_ping? 0 : ASSHELP_FLAG_AUTOSTART,
opt.verbose,
0,
NULL, NULL);
@ -441,11 +441,11 @@ static gpg_error_t
data_cb (void *opaque, const void *buffer, size_t length)
{
gpg_error_t err;
struct b64state *state = opaque;
gpgrt_b64state_t state = opaque;
if (buffer)
{
err = b64enc_write (state, buffer, length);
err = gpgrt_b64enc_write (state, buffer, length);
if (err)
log_error (_("error writing base64 encoding: %s\n"),
gpg_strerror (err));
@ -853,14 +853,14 @@ do_lookup (assuan_context_t ctx, const char *pattern)
gpg_error_t err;
const unsigned char *s;
char *line, *p;
struct b64state state;
gpgrt_b64state_t state;
if (opt.verbose)
log_info (_("looking up '%s'\n"), pattern);
err = b64enc_start (&state, stdout, NULL);
if (err)
return err;
state = gpgrt_b64enc_start (es_stdout, NULL);
if (!state)
return gpg_error_from_syserror ();
line = xmalloc (10 + 6 + 13 + strlen (pattern)*3 + 1);
@ -885,13 +885,13 @@ do_lookup (assuan_context_t ctx, const char *pattern)
err = assuan_transact (ctx, line,
data_cb, &state,
data_cb, state,
NULL, NULL,
status_cb, NULL);
if (opt.verbose > 1)
log_info ("response of dirmngr: %s\n", err? gpg_strerror (err): "okay");
err = b64enc_finish (&state);
err = gpgrt_b64enc_finish (state);
xfree (line);
return err;

View File

@ -394,6 +394,9 @@ static enum
} tor_mode;
/* Flag indicating that we are in supervised mode. */
static int is_supervised;
/* Counter for the active connections. */
static int active_connections;
@ -450,9 +453,6 @@ static void handle_connections (assuan_fd_t listen_fd);
static void gpgconf_versions (void);
/* NPth wrapper function definitions. */
ASSUAN_SYSTEM_NPTH_IMPL;
static const char *
my_strusage( int level )
{
@ -980,7 +980,6 @@ static void
thread_init (void)
{
npth_init ();
assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
/* Now with NPth running we can set the logging callback. Our
@ -1335,6 +1334,8 @@ main (int argc, char **argv)
if (!opt.quiet)
log_info(_("WARNING: \"%s\" is a deprecated option\n"), "--supervised");
is_supervised = 1;
/* In supervised mode, we expect file descriptor 3 to be an
already opened, listening socket.
@ -2233,7 +2234,7 @@ check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
if (assuan_sock_check_nonce (fd, nonce))
{
log_info (_("error reading nonce on fd %d: %s\n"),
FD2INT (fd), strerror (errno));
FD_DBG (fd), strerror (errno));
assuan_sock_close (fd);
return -1;
}
@ -2267,7 +2268,7 @@ start_connection_thread (void *arg)
active_connections++;
if (opt.verbose)
log_info (_("handler for fd %d started\n"), FD2INT (fd));
log_info (_("handler for fd %d started\n"), FD_DBG (fd));
session_id = ++last_session_id;
if (!session_id)
@ -2275,7 +2276,7 @@ start_connection_thread (void *arg)
start_command_handler (fd, session_id);
if (opt.verbose)
log_info (_("handler for fd %d terminated\n"), FD2INT (fd));
log_info (_("handler for fd %d terminated\n"), FD_DBG (fd));
active_connections--;
workqueue_run_post_session_tasks (session_id);
@ -2378,7 +2379,7 @@ handle_connections (assuan_fd_t listen_fd)
to full second. */
FD_ZERO (&fdset);
FD_SET (FD2INT (listen_fd), &fdset);
nfd = FD2INT (listen_fd);
nfd = FD2NUM (listen_fd);
if (my_inotify_fd != -1)
{
FD_SET (my_inotify_fd, &fdset);
@ -2395,7 +2396,7 @@ handle_connections (assuan_fd_t listen_fd)
/* Shutdown test. */
if (shutdown_pending)
{
if (!active_connections)
if (!active_connections || is_supervised)
break; /* ready */
/* Do not accept new connections but keep on running the
@ -2479,8 +2480,8 @@ handle_connections (assuan_fd_t listen_fd)
gnupg_fd_t fd;
plen = sizeof paddr;
fd = INT2FD (npth_accept (FD2INT(listen_fd),
(struct sockaddr *)&paddr, &plen));
fd = assuan_sock_accept (listen_fd,
(struct sockaddr *)&paddr, &plen);
if (fd == GNUPG_INVALID_FD)
{
log_error ("accept failed: %s\n", strerror (errno));
@ -2494,7 +2495,7 @@ handle_connections (assuan_fd_t listen_fd)
memset (&argval, 0, sizeof argval);
argval.afd = fd;
snprintf (threadname, sizeof threadname,
"conn fd=%d", FD2INT(fd));
"conn fd=%d", FD_DBG (fd));
ret = npth_create (&thread, &tattr,
start_connection_thread, argval.aptr);

View File

@ -107,7 +107,7 @@ static gpgrt_opt_t opts[] = {
" a record oriented format"},
{ oProxy, "proxy", 2,
"|NAME|ignore host part and connect through NAME"},
{ oStartTLS, "starttls", 0, "use STARTLS for the conenction"},
{ oStartTLS, "starttls", 0, "use STARTLS for the connection"},
{ oLdapTLS, "ldaptls", 0, "use a TLS for the connection"},
{ oNtds, "ntds", 0, "authenticate using AD"},
{ oARecOnly, "areconly", 0, "do only an A record lookup"},

View File

@ -34,6 +34,7 @@
# define WIN32_LEAN_AND_MEAN
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# include <ws2tcpip.h>
# endif
# include <windows.h>
# include <iphlpapi.h>

View File

@ -441,7 +441,7 @@ _my_socket_new (int lnr, assuan_fd_t fd)
so->refcount = 1;
if (opt_debug)
log_debug ("http.c:%d:socket_new: object %p for fd %d created\n",
lnr, so, (int)so->fd);
lnr, so, FD_DBG (so->fd));
return so;
}
#define my_socket_new(a) _my_socket_new (__LINE__, (a))
@ -453,7 +453,7 @@ _my_socket_ref (int lnr, my_socket_t so)
so->refcount++;
if (opt_debug > 1)
log_debug ("http.c:%d:socket_ref: object %p for fd %d refcount now %d\n",
lnr, so, (int)so->fd, so->refcount);
lnr, so, FD_DBG (so->fd), so->refcount);
return so;
}
#define my_socket_ref(a) _my_socket_ref (__LINE__,(a))
@ -471,7 +471,7 @@ _my_socket_unref (int lnr, my_socket_t so,
so->refcount--;
if (opt_debug > 1)
log_debug ("http.c:%d:socket_unref: object %p for fd %d ref now %d\n",
lnr, so, (int)so->fd, so->refcount);
lnr, so, FD_DBG (so->fd), so->refcount);
if (!so->refcount)
{
@ -2200,7 +2200,7 @@ run_ntbtls_handshake (http_t hd)
/* Until we support send/recv in estream under Windows we need
* to use es_fopencookie. */
# ifdef HAVE_W32_SYSTEM
in = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "rb",
in = es_fopencookie (hd->sock->fd, "rb",
simple_cookie_functions);
# else
in = es_fdopen_nc (hd->sock->fd, "rb");
@ -2212,7 +2212,7 @@ run_ntbtls_handshake (http_t hd)
}
# ifdef HAVE_W32_SYSTEM
out = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "wb",
out = es_fopencookie (hd->sock->fd, "wb",
simple_cookie_functions);
# else
out = es_fdopen_nc (hd->sock->fd, "wb");
@ -2362,7 +2362,6 @@ run_gnutls_handshake (http_t hd, const char *server)
* NULL, decode the string and use this as input from teh server. On
* success the final output token is stored at PROXY->OUTTOKEN and
* OUTTOKLEN. IF the authentication succeeded OUTTOKLEN is zero. */
#ifdef USE_TLS
static gpg_error_t
proxy_get_token (proxy_info_t proxy, const char *inputstring)
{
@ -2530,11 +2529,9 @@ proxy_get_token (proxy_info_t proxy, const char *inputstring)
#endif /*!HAVE_W32_SYSTEM*/
}
#endif /*USE_TLS*/
/* Use the CONNECT method to proxy our TLS stream. */
#ifdef USE_TLS
static gpg_error_t
run_proxy_connect (http_t hd, proxy_info_t proxy,
const char *httphost, const char *server,
@ -2556,6 +2553,7 @@ run_proxy_connect (http_t hd, proxy_info_t proxy,
* RFC-4559 - SPNEGO-based Kerberos and NTLM HTTP Authentication
*/
auth_basic = !!proxy->uri->auth;
hd->keep_alive = !auth_basic; /* We may need to send more requests. */
/* For basic authentication we need to send just one request. */
if (auth_basic
@ -2577,16 +2575,15 @@ run_proxy_connect (http_t hd, proxy_info_t proxy,
httphost ? httphost : server,
port,
authhdr ? authhdr : "",
auth_basic? "" : "Connection: keep-alive\r\n");
hd->keep_alive? "Connection: keep-alive\r\n" : "");
if (!request)
{
err = gpg_error_from_syserror ();
goto leave;
}
hd->keep_alive = !auth_basic; /* We may need to send more requests. */
if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
log_debug_with_string (request, "http.c:proxy:request:");
log_debug_string (request, "http.c:proxy:request:");
if (!hd->fp_write)
{
@ -2610,16 +2607,6 @@ run_proxy_connect (http_t hd, proxy_info_t proxy,
if (err)
goto leave;
{
unsigned long count = 0;
while (es_getc (hd->fp_read) != EOF)
count++;
if (opt_debug)
log_debug ("http.c:proxy_connect: skipped %lu bytes of response-body\n",
count);
}
/* Reset state. */
es_clearerr (hd->fp_read);
((cookie_t)(hd->read_cookie))->up_to_empty_line = 1;
@ -2730,6 +2717,14 @@ run_proxy_connect (http_t hd, proxy_info_t proxy,
}
leave:
if (hd->keep_alive)
{
es_fclose (hd->fp_write);
hd->fp_write = NULL;
/* The close has released the cookie and thus we better set it
* to NULL. */
hd->write_cookie = NULL;
}
/* Restore flags, destroy stream, reset state. */
hd->flags = saved_flags;
es_fclose (hd->fp_read);
@ -2743,7 +2738,6 @@ run_proxy_connect (http_t hd, proxy_info_t proxy,
xfree (tmpstr);
return err;
}
#endif /*USE_TLS*/
/* Make a request string using a standard proxy. On success the
@ -2882,7 +2876,7 @@ send_request (ctrl_t ctrl,
if (proxy && proxy->is_http_proxy)
{
use_http_proxy = 1; /* We want to use a proxy for the conenction. */
use_http_proxy = 1; /* We want to use a proxy for the connection. */
err = connect_server (ctrl,
*proxy->uri->host ? proxy->uri->host : "localhost",
proxy->uri->port ? proxy->uri->port : 80,
@ -2903,7 +2897,6 @@ send_request (ctrl_t ctrl,
goto leave;
}
#if USE_TLS
if (use_http_proxy && hd->uri->use_tls)
{
err = run_proxy_connect (hd, proxy, httphost, server, port);
@ -2915,7 +2908,6 @@ send_request (ctrl_t ctrl,
* clear the flag to indicate this. */
use_http_proxy = 0;
}
#endif /* USE_TLS */
#if HTTP_USE_NTBTLS
err = run_ntbtls_handshake (hd);
@ -3579,7 +3571,7 @@ connect_with_timeout (assuan_fd_t sock,
tval.tv_sec = timeout / 1000;
tval.tv_usec = (timeout % 1000) * 1000;
n = my_select (FD2INT(sock)+1, &rset, &wset, NULL, &tval);
n = my_select (FD2NUM(sock)+1, &rset, &wset, NULL, &tval);
if (n < 0)
{
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
@ -4411,7 +4403,7 @@ same_host_p (parsed_uri_t a, parsed_uri_t b)
}
/* Also consider hosts the same if they differ only in a subdomain;
* in both direction. This allows to have redirection between the
* in both direction. This allows one to have redirection between the
* WKD advanced and direct lookup methods. */
for (i=0; i < DIM (subdomains); i++)
{

View File

@ -373,6 +373,8 @@ ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|| !strcmp (uri->parsed_uri->scheme, "ldaps")
|| !strcmp (uri->parsed_uri->scheme, "ldapi")
|| uri->parsed_uri->opaque);
#else
(void)newer;
#endif
if (is_hkp_s || is_http_s || is_ldap)
@ -590,6 +592,13 @@ ks_action_query (ctrl_t ctrl, const char *url, unsigned int ks_get_flags,
return err;
#else /* !USE_LDAP */
(void)ctrl;
(void)url;
(void)ks_get_flags;
(void)filter;
(void)attrs;
(void)newer;
(void)outfp;
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
#endif
}

View File

@ -31,6 +31,8 @@
# define WINVER 0x0500 /* Same as in common/sysutils.c */
# endif
# include <winsock2.h>
# include <winldap.h>
# include <winber.h>
# include <sddl.h>
#endif
@ -605,7 +607,7 @@ interrogate_ldap_dn (LDAP *ldap_conn, const char *basedn_search,
* including whether to use TLS and the username and password (see
* ldap_parse_uri for a description of the various fields). Be
* default a PGP keyserver is assumed; if GENERIC is true a generic
* ldap conenction is instead established.
* ldap connection is instead established.
*
* Returns: The ldap connection handle in *LDAP_CONNP, R_BASEDN is set
* to the base DN for the PGP key space, several flags will be stored

View File

@ -87,7 +87,7 @@ struct wrapper_context_s
{
struct wrapper_context_s *next;
pid_t pid; /* The pid of the wrapper process. */
gnupg_process_t proc;/* The wrapper process. */
int printable_pid; /* Helper to print diagnostics after the process has
* been cleaned up. */
estream_t fp; /* Connected with stdout of the ldap wrapper. */
@ -170,10 +170,10 @@ read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
static void
destroy_wrapper (struct wrapper_context_s *ctx)
{
if (ctx->pid != (pid_t)(-1))
if (ctx->proc)
{
gnupg_kill_process (ctx->pid);
gnupg_release_process (ctx->pid);
gnupg_process_terminate (ctx->proc);
gnupg_process_release (ctx->proc);
}
ksba_reader_release (ctx->reader);
SAFE_CLOSE (ctx->fp);
@ -260,7 +260,7 @@ read_log_data (struct wrapper_context_s *ctx)
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
return 0;
log_error (_("error reading log from ldap wrapper %d: %s\n"),
(int)ctx->pid, gpg_strerror (err));
ctx->printable_pid, gpg_strerror (err));
}
print_log_line (ctx, NULL); /* Flush. */
SAFE_CLOSE (ctx->log_fp);
@ -438,50 +438,44 @@ ldap_reaper_thread (void *dummy)
}
/* Check whether the process is still running. */
if (ctx->pid != (pid_t)(-1))
if (ctx->proc)
{
int status;
err = gnupg_wait_process ("[dirmngr_ldap]", ctx->pid, 0,
&status);
err = gnupg_process_wait (ctx->proc, 0);
if (!err)
{
int status;
gnupg_process_ctl (ctx->proc, GNUPG_PROCESS_GET_EXIT_ID,
&status);
if (DBG_EXTPROG)
log_info (_("ldap wrapper %d ready"), (int)ctx->pid);
log_info (_("ldap wrapper %d ready"), ctx->printable_pid);
ctx->ready = 1;
gnupg_release_process (ctx->pid);
ctx->pid = (pid_t)(-1);
gnupg_process_release (ctx->proc);
ctx->proc = NULL;
any_action = 1;
}
else if (gpg_err_code (err) == GPG_ERR_GENERAL)
{
if (status == 10)
log_info (_("ldap wrapper %d ready: timeout\n"),
(int)ctx->pid);
ctx->printable_pid);
else
log_info (_("ldap wrapper %d ready: exitcode=%d\n"),
(int)ctx->pid, status);
ctx->ready = 1;
gnupg_release_process (ctx->pid);
ctx->pid = (pid_t)(-1);
any_action = 1;
ctx->printable_pid, status);
}
else if (gpg_err_code (err) != GPG_ERR_TIMEOUT)
{
log_error (_("waiting for ldap wrapper %d failed: %s\n"),
(int)ctx->pid, gpg_strerror (err));
ctx->printable_pid, gpg_strerror (err));
any_action = 1;
}
}
/* Check whether we should terminate the process. */
if (ctx->pid != (pid_t)(-1)
&& ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
if (ctx->proc && ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
{
gnupg_kill_process (ctx->pid);
gnupg_process_terminate (ctx->proc);
ctx->stamp = (time_t)(-1);
log_info (_("ldap wrapper %d stalled - killing\n"),
(int)ctx->pid);
ctx->printable_pid);
/* We need to close the log stream because the cleanup
* loop waits for it. */
SAFE_CLOSE (ctx->log_fp);
@ -496,10 +490,10 @@ ldap_reaper_thread (void *dummy)
{
log_debug ("ldap worker states:\n");
for (ctx = reaper_list; ctx; ctx = ctx->next)
log_debug (" c=%p pid=%d/%d rdr=%p logfp=%p"
log_debug (" c=%p pid=%d rdr=%p logfp=%p"
" ctrl=%p/%d la=%lu rdy=%d\n",
ctx,
(int)ctx->pid, (int)ctx->printable_pid,
ctx->printable_pid,
ctx->reader, ctx->log_fp,
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0,
(unsigned long)ctx->stamp, ctx->ready);
@ -602,9 +596,9 @@ ldap_wrapper_release_context (ksba_reader_t reader)
if (ctx->reader == reader)
{
if (DBG_EXTPROG)
log_debug ("releasing ldap worker c=%p pid=%d/%d rdr=%p"
log_debug ("releasing ldap worker c=%p pid=%d rdr=%p"
" ctrl=%p/%d\n", ctx,
(int)ctx->pid, (int)ctx->printable_pid,
ctx->printable_pid,
ctx->reader,
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0);
@ -639,8 +633,8 @@ ldap_wrapper_connection_cleanup (ctrl_t ctrl)
{
ctx->ctrl->refcount--;
ctx->ctrl = NULL;
if (ctx->pid != (pid_t)(-1))
gnupg_kill_process (ctx->pid);
if (ctx->proc)
gnupg_process_terminate (ctx->proc);
if (ctx->fp_err)
log_info ("%s: reading from ldap wrapper %d failed: %s\n",
__func__, ctx->printable_pid, gpg_strerror (ctx->fp_err));
@ -798,7 +792,7 @@ gpg_error_t
ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
{
gpg_error_t err;
pid_t pid;
gnupg_process_t process;
struct wrapper_context_s *ctx;
int i;
int j;
@ -854,19 +848,22 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
return err;
}
err = gnupg_spawn_process (pgmname, arg_list,
NULL, GNUPG_SPAWN_NONBLOCK,
NULL, &outfp, &errfp, &pid);
err = gnupg_process_spawn (pgmname, arg_list,
(GNUPG_PROCESS_STDOUT_PIPE
| GNUPG_PROCESS_STDERR_PIPE),
NULL, NULL, &process);
if (err)
{
xfree (arg_list);
xfree (arg_list);
xfree (ctx);
log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
return err;
}
gnupg_process_get_streams (process, GNUPG_PROCESS_STREAM_NONBLOCK,
NULL, &outfp, &errfp);
gnupg_process_ctl (process, GNUPG_PROCESS_GET_PROC_ID, &ctx->printable_pid);
ctx->pid = pid;
ctx->printable_pid = (int) pid;
ctx->proc = process;
ctx->fp = outfp;
ctx->log_fp = errfp;
ctx->ctrl = ctrl;
@ -902,7 +899,7 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
if (DBG_EXTPROG)
{
log_debug ("ldap wrapper %d started (%p, %s)",
(int)ctx->pid, ctx->reader, pgmname);
ctx->printable_pid, ctx->reader, pgmname);
for (i=0; arg_list[i]; i++)
log_printf (" [%s]", arg_list[i]);
log_printf ("\n");

View File

@ -583,7 +583,7 @@ gpg_error_t
armor_data (char **r_string, const void *data, size_t datalen)
{
gpg_error_t err;
struct b64state b64state;
gpgrt_b64state_t b64state;
estream_t fp;
long length;
char *buffer;
@ -595,9 +595,15 @@ armor_data (char **r_string, const void *data, size_t datalen)
if (!fp)
return gpg_error_from_syserror ();
if ((err=b64enc_start_es (&b64state, fp, "PGP PUBLIC KEY BLOCK"))
|| (err=b64enc_write (&b64state, data, datalen))
|| (err = b64enc_finish (&b64state)))
b64state = gpgrt_b64enc_start (fp, "PGP PUBLIC KEY BLOCK");
if (!b64state)
{
es_fclose (fp);
return gpg_error_from_syserror ();
}
if ((err = gpgrt_b64enc_write (b64state, data, datalen))
|| (err = gpgrt_b64enc_finish (b64state)))
{
es_fclose (fp);
return err;

View File

@ -3325,7 +3325,7 @@ dirmngr_status_help (ctrl_t ctrl, const char *text)
/* Print a help status line using a printf like format. The function
* splits text at LFs. With CTRL beeing NULL, the function behaves
* splits text at LFs. With CTRL being NULL, the function behaves
* like log_info. */
gpg_error_t
dirmngr_status_helpf (ctrl_t ctrl, const char *format, ...)

View File

@ -167,11 +167,13 @@ described here.
The value is quoted like a C string to avoid control characters
(the colon is quoted =\x3a=). For a "pub" record this field is
not used on --fixed-list-mode. A UAT record puts the attribute
not used on --fixed-list-mode. A "uat" record puts the attribute
subpacket count here, a space, and then the total attribute
subpacket size. In gpgsm the issuer name comes here. The FPR and FP2
records store the fingerprints here. The fingerprint of a
revocation key is stored here.
subpacket size. In gpgsm the issuer name comes here. The FPR and
FP2 records store the fingerprints here. The fingerprint of a
revocation key is also stored here. A "grp" records puts the
keygrip here; for combined algorithms the keygrips are delimited
by comma.
*** Field 11 - Signature class
@ -243,7 +245,8 @@ described here.
*** Field 17 - Curve name
For pub, sub, sec, ssb, crt, and crs records this field is used
for the ECC curve name.
for the ECC curve name. For combined algorithms the first and the
second algorithm name, delimited by an underscore are put here.
*** Field 18 - Compliance flags
@ -527,6 +530,12 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
--assert-signer is used. The fingerprint is printed with
uppercase hex digits.
*** ASSERT_PUBKEY_ALGO <fingerprint> <state> <algostr>
This is emitted when option --assert-pubkey-algo is used and the
signing algorithms is accepted according to that list if state is
1 or denied if state is 0. The fingerprint is printed with
uppercase hex digits.
*** SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp>
This is emitted only for signatures of class 0 or 1 which have
been verified okay. The string is a signature id and may be used

View File

@ -42,7 +42,7 @@ EXTRA_DIST = samplekeys.asc mksamplekeys com-certs.pem \
FAQ gnupg7.texi mkdefsinc.c defsincdate \
opt-homedir.texi see-also-note.texi specify-user-id.texi \
gpgv.texi yat2m.c ChangeLog-2011 whats-new-in-2.1.txt \
trust-values.texi
trust-values.texi keyformat.txt
BUILT_SOURCES = gnupg-module-overview.png gnupg-module-overview.pdf \
gnupg-card-architecture.png gnupg-card-architecture.pdf \

View File

@ -91,7 +91,7 @@ should not occur but sometimes things go wrong), run it using
@item How to find the IP address of a keyserver
If a round robin URL of is used for a keyserver
(e.g. subkeys.gnupg.org); it is not easy to see what server is actually
(e.g., subkeys.gnupg.org); it is not easy to see what server is actually
used. Using the keyserver debug option as in
@smallexample
@ -130,7 +130,7 @@ but Dirmngr's OCSP feature has not been enabled using
The far most common reason for this is that the environment variable
@code{GPG_TTY} has not been set correctly. Make sure that it has been
set to a real tty device and not just to @samp{/dev/tty};
i.e. @samp{GPG_TTY=tty} is plainly wrong; what you want is
i.e., @samp{GPG_TTY=tty} is plainly wrong; what you want is
@samp{GPG_TTY=`tty`} --- note the back ticks. Also make sure that
this environment variable gets exported, that is you should follow up
the setting with an @samp{export GPG_TTY} (assuming a Bourne style

View File

@ -172,7 +172,7 @@ socket.
Set compatibility flags to work around certain problems or to emulate
bugs. The @var{flags} are given as a comma separated list of flag
names and are OR-ed together. The special flag "none" clears the list
and allows to start over with an empty list. To get a list of
and allows one to start over with an empty list. To get a list of
available flags the sole word "help" can be used.
@item --faked-system-time @var{epoch}
@ -213,7 +213,7 @@ however carefully selected to best aid in debugging.
@item --debug @var{flags}
@opindex debug
Set debug flags. All flags are or-ed and @var{flags} may be given in
C syntax (e.g. 0x0042) or as a comma separated list of flag names. To
C syntax (e.g., 0x0042) or as a comma separated list of flag names. To
get a list of all supported flags the single word "help" can be used.
This option is only useful for debugging and the behavior may change
at any time without notice.
@ -295,7 +295,7 @@ seconds.
@opindex connect-quick-timeout
Set the timeout for HTTP and generic TCP connection attempts to N
seconds. The value set with the quick variant is used when the
--quick option has been given to certain Assuan commands. The quick
@option{--quick} option has been given to certain Assuan commands. The quick
value is capped at the value of the regular connect timeout. The
default values are 15 and 2 seconds. Note that the timeout values are
for each connection attempt; the connection code will attempt to
@ -375,7 +375,7 @@ there for details; here is an example:
as given. Replace USERNAME, PASSWORD, and the 'dc' parts
according to the instructions received from your LDAP
administrator. Note that only simple authentication
(i.e. cleartext passwords) is supported and thus using ldaps is
(i.e., cleartext passwords) is supported and thus using ldaps is
strongly suggested (since 2.2.28 "ldaps" defaults to port 389
and uses STARTTLS). On Windows authentication via AD can be
requested by adding @code{gpgNtds=1} after the fourth question
@ -468,7 +468,7 @@ Lines starting with a @samp{#} are comments.
Note that as usual all strings entered are expected to be UTF-8 encoded.
Obviously this will lead to problems if the password has originally been
encoded as Latin-1. There is no other solution here than to put such a
password in the binary encoding into the file (i.e. non-ascii characters
password in the binary encoding into the file (i.e., non-ascii characters
won't show up readable).@footnote{The @command{gpgconf} tool might be
helpful for frontends as it enables editing this configuration file using
percent-escaped strings.}
@ -684,7 +684,7 @@ those certificates on startup and when given a SIGHUP. Certificates
which are not readable or do not make up a proper X.509 certificate
are ignored; see the log file for details.
Applications using dirmngr (e.g. gpgsm) can request these
Applications using dirmngr (e.g., gpgsm) can request these
certificates to complete a trust chain in the same way as with the
extra-certs directory (see below).
@ -693,7 +693,7 @@ Note that for OCSP responses the certificate specified using the option
@item /etc/gnupg/extra-certs
This directory may contain extra certificates which are preloaded
into the internal cache on startup. Applications using dirmngr (e.g. gpgsm)
into the internal cache on startup. Applications using dirmngr (e.g., gpgsm)
can request cached certificates to complete a trust chain.
This is convenient in cases you have a couple intermediate CA certificates
or certificates usually used to sign OCSP responses.
@ -752,7 +752,7 @@ certificate exists it is used to access the special keyservers
Please note that @command{gpgsm} accepts Root CA certificates for its
own purposes only if they are listed in its file @file{trustlist.txt}.
@command{dirmngr} does not make use of this list - except FIXME.
@command{dirmngr} does not make use of this list --- except FIXME.
@mansect notes
@ -802,7 +802,7 @@ Enter @code{HELP} at the prompt to see a list of commands and enter
@node Dirmngr Signals
@section Use of signals
A running @command{dirmngr} may be controlled by signals, i.e. using
A running @command{dirmngr} may be controlled by signals, i.e., using
the @command{kill} command to send a signal to the process.
Here is a list of supported signals:
@ -1034,7 +1034,7 @@ includes a local certificate store as well as a list of trusted root
certificates.
@noindent
The return code is 0 for success; i.e. the certificate has not been
The return code is 0 for success; i.e., the certificate has not been
revoked or one of the usual error codes from libgpg-error.
@node Dirmngr CHECKOCSP
@ -1069,7 +1069,7 @@ of the global option @option{--ignore-ocsp-service-url}.
@noindent
The return code is 0 for success; i.e. the certificate has not been
The return code is 0 for success; i.e., the certificate has not been
revoked or one of the usual error codes from libgpg-error.
@node Dirmngr CACHECERT
@ -1091,7 +1091,7 @@ Thus the caller is expected to return the certificate for the request
as a binary blob.
@noindent
The return code is 0 for success; i.e. the certificate has not been
The return code is 0 for success; i.e., the certificate has not been
successfully cached or one of the usual error codes from libgpg-error.
@node Dirmngr VALIDATE
@ -1191,7 +1191,7 @@ as a binary blob.
@c does not yet end up in memory.
@c * @code{crl_cache_insert} is called with that descriptor to
@c actually read the CRL into the cache. See below for a
@c description of this function. If there is any error (e.g. read
@c description of this function. If there is any error (e.g., read
@c problem, CRL not correctly signed or verification of signature
@c not possible), this descriptor is rejected and we continue
@c with the next name. If the CRL has been successfully loaded,
@ -1217,7 +1217,7 @@ as a binary blob.
@c a) An authorityKeyIdentifier with an issuer and serialno exits: The
@c certificate is retrieved using @code{find_cert_bysn}. If
@c the certificate is in the certificate cache, it is directly
@c returned. Then the requester (i.e. the client who requested the
@c returned. Then the requester (i.e., the client who requested the
@c CRL check) is asked via the Assuan inquiry ``SENDCERT'' whether
@c he can provide this certificate. If this succeed the returned
@c certificate gets cached and returned. Note, that dirmngr does not
@ -1296,7 +1296,7 @@ as a binary blob.
@c expiration time of all certificates in the chain.
@c
@c We first check that the certificate may be used for the requested
@c purpose (i.e. OCSP or CRL signing). If this is not the case
@c purpose (i.e., OCSP or CRL signing). If this is not the case
@c GPG_ERR_WRONG_KEY_USAGE is returned.
@c
@c The next step is to find the trust anchor (root certificate) and to
@ -1320,7 +1320,7 @@ as a binary blob.
@c Now the issuer's certificate is looked up: If an
@c authorityKeyIdentifier is available, this one is used to locate the
@c certificate either using issuer and serialnumber or subject DN
@c (i.e. the issuer's DN) and the keyID. The functions
@c (i.e., the issuer's DN) and the keyID. The functions
@c @code{find_cert_bysn) and @code{find_cert_bysubject} are used
@c respectively. The have already been described above under the
@c description of @code{crl_cache_insert}. If no certificate was found
@ -1334,13 +1334,13 @@ as a binary blob.
@c actual certificate is checked and in case this fails the error
@c #code{GPG_ERR_BAD_CERT_CHAIN} is returned. If the signature checks out, the
@c maximum chain length of the issuing certificate is checked as well as
@c the capability of the certificate (i.e. whether he may be used for
@c the capability of the certificate (i.e., whether he may be used for
@c certificate signing). Then the certificate is prepended to our list
@c representing the certificate chain. Finally the loop is continued now
@c with the issuer's certificate as the current certificate.
@c
@c After the end of the loop and if no error as been encountered
@c (i.e. the certificate chain has been assempled correctly), a check is
@c (i.e., the certificate chain has been assempled correctly), a check is
@c done whether any certificate expired or a critical policy has not been
@c met. In any of these cases the validation terminates with an
@c appropriate error.

View File

@ -72,7 +72,7 @@ the included Secure Shell Agent you may start the agent using:
@c One way of enforcing this split is a per-key or per-session
@c passphrase, known only by the owner, which must be supplied to the
@c agent to permit the use of the secret key material. Another way is
@c with an out-of-band permission mechanism (e.g. a button or GUI
@c with an out-of-band permission mechanism (e.g@:. a button or GUI
@c interface that the owner has access to, but the supplicant does not).
@c
@c The rationale for this separation is that it allows access to the
@ -111,8 +111,8 @@ Please make sure that a proper pinentry program has been installed
under the default filename (which is system dependent) or use the
option @option{pinentry-program} to specify the full name of that program.
It is often useful to install a symbolic link from the actual used
pinentry (e.g. @file{@value{BINDIR}/pinentry-gtk}) to the expected
one (e.g. @file{@value{BINDIR}/pinentry}).
pinentry (e.g., @file{@value{BINDIR}/pinentry-gtk}) to the expected
one (e.g., @file{@value{BINDIR}/pinentry}).
@manpause
@noindent
@ -177,8 +177,8 @@ Windows.
If in @file{common.conf} the option @option{no-autostart} is set, any
start attempts will be ignored.
In --supervised mode, different file descriptors can be provided for
use as different socket types (e.g. ssh, extra) as long as they are
In @option{--supervised} mode, different file descriptors can be provided for
use as different socket types (e.g., ssh, extra) as long as they are
identified in the environment variable @code{LISTEN_FDNAMES} (see
sd_listen_fds(3) on some Linux distributions for more information on
this convention).
@ -259,7 +259,7 @@ however carefully selected to best aid in debugging.
@item --debug @var{flags}
@opindex debug
Set debug flags. All flags are or-ed and @var{flags} may be given
in C syntax (e.g. 0x0042) or as a comma separated list of flag names.
in C syntax (e.g., 0x0042) or as a comma separated list of flag names.
To get a list of all supported flags the single word "help" can be
used. This option is only useful for debugging and the behavior may
change at any time without notice.
@ -302,7 +302,7 @@ debugging.
@item --steal-socket
@opindex steal-socket
In @option{--daemon} mode, gpg-agent detects an already running
gpg-agent and does not allow to start a new instance. This option can
gpg-agent and does not allow one to start a new instance. This option can
be used to override this check: the new gpg-agent process will try to
take over the communication sockets from the already running process
and start anyway. This option should in general not be used.
@ -345,7 +345,7 @@ specify the logging output.
@anchor{option --no-allow-mark-trusted}
@item --no-allow-mark-trusted
@opindex no-allow-mark-trusted
Do not allow clients to mark keys as trusted, i.e. put them into the
Do not allow clients to mark keys as trusted, i.e., put them into the
@file{trustlist.txt} file. This makes it harder for users to inadvertently
accept Root-CA keys.
@ -643,7 +643,7 @@ gpg-agent as a replacement for PuTTY's Pageant, the option
In this mode of operation, the agent does not only implement the
gpg-agent protocol, but also the agent protocol used by OpenSSH
(through a separate socket or via Named Pipes) or the protocol used by
PuTTY. Consequently, this allows to use the gpg-agent as a drop-in
PuTTY. Consequently, this allows one to use the gpg-agent as a drop-in
replacement for the ssh-agent.
SSH keys, which are to be used through the agent, need to be added to
@ -693,7 +693,7 @@ The order in which keys are presented to ssh are:
@item Negative Use-for-ssh values
If a key file has the attribute "Use-for-ssh" and its value is
negative, these keys are presented first to ssh. The negative
values are capped at -999 with -999 beeing lower ranked than -1.
values are capped at -999 with -999 being lower ranked than -1.
These values can be used to prefer on-disk keys over keys taken
from active cards.
@ -716,7 +716,7 @@ The order in which keys are presented to ssh are:
Editing the "Use-for-ssh" values can be done with an editor or using
@command{gpg-connect-agent} and "KEYATTR" (Remember to append a colon
to the key; i.e. use "Use-for-ssh:").
to the key; i.e., use "Use-for-ssh:").
@anchor{option --ssh-fingerprint-digest}
@ -724,7 +724,7 @@ to the key; i.e. use "Use-for-ssh:").
@opindex ssh-fingerprint-digest
Select the digest algorithm used to compute ssh fingerprints that are
communicated to the user, e.g. in pinentry dialogs. OpenSSH has
communicated to the user, e.g., in pinentry dialogs. OpenSSH has
transitioned from using MD5 to the more secure SHA256.
@ -830,7 +830,7 @@ It might even be advisable to change the permissions to read-only so
that this file can't be changed inadvertently.
As a special feature a line @code{include-default} will include a global
list of trusted certificates (e.g. @file{@value{SYSCONFDIR}/trustlist.txt}).
list of trusted certificates (e.g., @file{@value{SYSCONFDIR}/trustlist.txt}).
This global list is also used if the local list is not available;
the @ref{option --no-user-trustlist} enforces the use of only
this global list.
@ -892,7 +892,7 @@ The keygrip may be prefixed with a @code{!} to disable an entry.
The following example lists exactly one key. Note that keys available
through a OpenPGP smartcard in the active smartcard reader are
implicitly added to this list; i.e. there is no need to list them.
implicitly added to this list; i.e., there is no need to list them.
@cartouche
@smallexample
@ -925,7 +925,7 @@ a small helper script is provided to create these files (@pxref{addgnupghome}).
@mansect signals
@node Agent Signals
@section Use of some signals
A running @command{gpg-agent} may be controlled by signals, i.e. using
A running @command{gpg-agent} may be controlled by signals, i.e., using
the @command{kill} command to send a signal to the process.
Here is a list of supported signals:
@ -1407,7 +1407,7 @@ convention either the hexified fingerprint of the key shall be used for
calling application and a colon: Like @code{gpg:somestring}.
@var{error_message} is either a single @code{X} for no error message or
a string to be shown as an error message like (e.g. "invalid
a string to be shown as an error message like (e.g., "invalid
passphrase"). Blanks must be percent escaped or replaced by @code{+}'.
@var{prompt} is either a single @code{X} for a default prompt or the

View File

@ -226,7 +226,7 @@ OpenPGP or X.509 keys.
@item LOGIN [--clear] [< @var{file}]
@opindex login
Set the login data object of OpenPGP cards. If @var{file} is given
the data is is read from that file. This allows to store binary data
the data is is read from that file. This allows one to store binary data
in the login field. The option @option{--clear} deletes the login
data object.
@ -546,7 +546,7 @@ be printed; to create a new key anyway the option @samp{--force} can be
used. Note that only the private and public keys have been created
but no certificates are stored in the key slots. In fact, GnuPG uses
its own non-standard method to store just the public key in place of
the the certificate. Other application will not be able to make use
the certificate. Other application will not be able to make use
these keys until @command{gpgsm} or another tool has been used to
create and store the respective certificates. Let us see what the
list command now shows:

View File

@ -330,21 +330,21 @@ The status of the verification is indicated by a flag directly
following the "sig" tag (and thus before the flags described below. A
"!" indicates that the signature has been successfully verified, a "-"
denotes a bad signature and a "%" is used if an error occurred while
checking the signature (e.g. a non supported algorithm). Signatures
checking the signature (e.g., a non supported algorithm). Signatures
where the public key is not available are not listed; to see their
keyids the command @option{--list-sigs} can be used.
For each signature listed, there are several flags in between the
signature status flag and keyid. These flags give additional
information about each key signature. From left to right, they are
the numbers 1-3 for certificate check level (see
the numbers 1--3 for certificate check level (see
@option{--ask-cert-level}), "L" for a local or non-exportable
signature (see @option{--lsign-key}), "R" for a nonRevocable signature
(see the @option{--edit-key} command "nrsign"), "P" for a signature
that contains a policy URL (see @option{--cert-policy-url}), "N" for a
signature that contains a notation (see @option{--cert-notation}), "X"
for an eXpired signature (see @option{--ask-cert-expire}), and the
numbers 1-9 or "T" for 10 and above to indicate trust signature levels
numbers 1--9 or "T" for 10 and above to indicate trust signature levels
(see the @option{--edit-key} command "tsign").
@ -362,9 +362,9 @@ public keys are listed.
The variant @option{--locate-external-keys} does not consider a
locally existing key and can thus be used to force the refresh of a
key via the defined external methods. If a fingerprint is given and
and the methods defined by --auto-key-locate define LDAP servers, the
key is fetched from these resources; defined non-LDAP keyservers are
skipped.
and the methods defined by @option{--auto-key-locate} define LDAP
servers, the key is fetched from these resources; defined non-LDAP
keyservers are skipped.
@item --show-keys
@ -405,7 +405,7 @@ description, please see the Card HOWTO at
https://gnupg.org/documentation/howtos.html#GnuPG-cardHOWTO . Please
note that the command "openpgp" can be used to switch to the OpenPGP
application of cards which by default are presenting another
application (e.g. PIV).
application (e.g., PIV).
@item --card-status
@opindex card-status
@ -589,7 +589,7 @@ corrupted trustdb. Example:
Update the trustdb with the ownertrust values stored in @code{files} (or
STDIN if not given); existing values will be overwritten. In case of a
severely damaged trustdb and if you have a recent backup of the
ownertrust values (e.g. in the file @file{otrust.txt}), you may re-create
ownertrust values (e.g., in the file @file{otrust.txt}), you may re-create
the trustdb using these commands:
@c man:.RS
@example
@ -716,7 +716,7 @@ inserted smartcard, the special string ``card'' can be used for
will figure them out and creates an OpenPGP key consisting of the
usual primary key and one subkey. This works only with certain
smartcards. Note that the interactive @option{--full-gen-key} command
allows to do the same but with greater flexibility in the selection of
allows one to do the same but with greater flexibility in the selection of
the smartcard keys.
Note that it is possible to create a primary key and a subkey using
@ -892,7 +892,7 @@ signing.
@item delsig
@opindex keyedit:delsig
Delete a signature. Note that it is not possible to retract a signature,
once it has been send to the public (i.e. to a keyserver). In that case
once it has been send to the public (i.e., to a keyserver). In that case
you better use @code{revsig}.
@item revsig
@ -926,7 +926,7 @@ signing.
@opindex keyedit:deluid
Delete a user ID or photographic user ID. Note that it is not
possible to retract a user id, once it has been send to the public
(i.e. to a keyserver). In that case you better use @code{revuid}.
(i.e., to a keyserver). In that case you better use @code{revuid}.
@item revuid
@opindex keyedit:revuid
@ -1005,13 +1005,13 @@ signing.
@item keytocard
@opindex keyedit:keytocard
Transfer the selected secret subkey (or the primary key if no subkey
has been selected) to a smartcard. The secret key in the keyring will
be replaced by a stub if the key could be stored successfully on the
card and you use the save command later. Only certain key types may be
transferred to the card. A sub menu allows you to select on what card
to store the key. Note that it is not possible to get that key back
from the card - if the card gets broken your secret key will be lost
unless you have a backup somewhere.
has been selected) to a smartcard. The secret key in the keyring
will be replaced by a stub if the key could be stored successfully
on the card and you use the save command later. Only certain key
types may be transferred to the card. A sub menu allows you to
select on what card to store the key. Note that it is not possible
to get that key back from the card --- if the card gets broken your
secret key will be lost unless you have a backup somewhere.
@item bkuptocard @var{file}
@opindex keyedit:bkuptocard
@ -1046,7 +1046,7 @@ signing.
@item delkey
@opindex keyedit:delkey
Remove a subkey (secondary key). Note that it is not possible to retract
a subkey, once it has been send to the public (i.e. to a keyserver). In
a subkey, once it has been send to the public (i.e., to a keyserver). In
that case you better use @code{revkey}. Also note that this only
deletes the public part of a key.
@ -1098,7 +1098,7 @@ signing.
@item clean
@opindex keyedit:clean
Compact (by removing all signatures except the selfsig) any user ID
that is no longer usable (e.g. revoked, or expired). Then, remove any
that is no longer usable (e.g., revoked, or expired). Then, remove any
signatures that are not usable by the trust calculations.
Specifically, this removes any signature that does not validate, any
signature that is superseded by a later signature, revoked signatures,
@ -1112,7 +1112,7 @@ signing.
@item change-usage
@opindex keyedit:change-usage
Change the usage flags (capabilities) of the primary key or of
subkeys. These usage flags (e.g. Certify, Sign, Authenticate,
subkeys. These usage flags (e.g., Certify, Sign, Authenticate,
Encrypt) are set during key creation. Sometimes it is useful to
have the opportunity to change them (for example to add
Authenticate) after they have been created. Please take care when
@ -1223,12 +1223,19 @@ all affected self-signatures is set one second ahead.
This command updates the preference list of the key to the current
default value (either built-in or set via
@option{--default-preference-list}). This is the unattended version
of of using "setpref" in the @option{--key-edit} menu without giving a
of using "setpref" in the @option{--key-edit} menu without giving a
list. Note that you can show the preferences in a key listing by
using @option{--list-options show-pref} or @option{--list-options
show-pref-verbose}. You should also re-distribute updated keys to
your peers.
@item --quick-set-ownertrust @var{user-id} @var{value}
@opindex quick-set-ownertrust
This command sets the ownertrust of a key and can also be used to set
the disable flag of a key. This is the unattended version of using
"trust", "disable", or "enable" in the @option{--key-edit} menu.
@item --change-passphrase @var{user-id}
@opindex change-passphrase
@itemx --passwd @var{user-id}
@ -1265,13 +1272,13 @@ behaviour and to change the default configuration.
@end menu
Long options can be put in an options file (default
"~/.gnupg/gpg.conf"). Short option names will not work - for example,
"armor" is a valid option for the options file, while "a" is not. Do not
write the 2 dashes, but simply the name of the option and any required
arguments. Lines with a hash ('#') as the first non-white-space
character are ignored. Commands may be put in this file too, but that is
not generally useful as the command will execute automatically with
every execution of gpg.
"~/.gnupg/gpg.conf"). Short option names will not work --- for
example, "armor" is a valid option for the options file, while "a" is
not. Do not write the 2 dashes, but simply the name of the option and
any required arguments. Lines with a hash ('#') as the first
non-white-space character are ignored. Commands may be put in this
file too, but that is not generally useful as the command will execute
automatically with every execution of gpg.
Please remember that option parsing stops as soon as a non-option is
encountered, you can explicitly stop parsing by using the special option
@ -1290,19 +1297,22 @@ are usually found in the option file.
@item --default-key @var{name}
@opindex default-key
Use @var{name} as the default key to sign with. If this option is not
used, the default key is the first key found in the secret keyring.
Note that @option{-u} or @option{--local-user} overrides this option.
This option may be given multiple times. In this case, the last key
for which a secret key is available is used. If there is no secret
key available for any of the specified values, GnuPG will not emit an
error message but continue as if this option wasn't given.
Use @var{name} as the default key to sign with. It is suggested to
use a fingerprint or at least a long keyID for @var{name}. If this
option is not used, the default key is the first key found in the
secret keyring. Note that @option{-u} or @option{--local-user}
overrides this option. This option may be given multiple times. In
this case, the last key for which a secret key is available is used.
If there is no secret key available for any of the specified values,
GnuPG will not emit an error message but continue as if this option
wasn't given.
@item --default-recipient @var{name}
@opindex default-recipient
Use @var{name} as default recipient if option @option{--recipient} is
not used and don't ask if this is a valid one. @var{name} must be
non-empty.
non-empty and it is suggested to use a fingerprint for @var{name}.
@item --default-recipient-self
@opindex default-recipient-self
@ -1393,6 +1403,11 @@ give the opposite meaning. The options are:
key (@code{E}=encryption, @code{S}=signing, @code{C}=certification,
@code{A}=authentication). Defaults to yes.
@item show-ownertrust
@opindex list-options:show-ownertrust
Show the ownertrust value for keys also in the standard key
listing. Defaults to no.
@item show-policy-urls
@opindex list-options:show-policy-urls
Show policy URLs in the @option{--check-signatures}
@ -1407,6 +1422,18 @@ give the opposite meaning. The options are:
Show all, IETF standard, or user-defined signature notations in the
@option{--check-signatures} listings. Defaults to no.
@item show-x509-notations
@opindex list-options:show-x509-notations
Print X.509 certificates embedded in key signatures as PEM data.
This is intended for debugging and the output format may change
without notice.
@item store-x509-notations
@opindex list-options:store-x509-notations
Store X.509 certificates embedded in key signatures as PEM data
files. The filename consists the 4 byte key ID of the certificate,
a dash, the fingerprint of the key or subkey, and the suffix ".pem".
@item show-keyserver-urls
@opindex list-options:show-keyserver-urls
Show any preferred keyserver URL in the
@ -1454,10 +1481,10 @@ give the opposite meaning. The options are:
@item sort-sigs
@opindex list-options:sort-sigs
With --list-sigs and --check-sigs sort the signatures by keyID and
creation time to make it easier to view the history of these
signatures. The self-signature is also listed before other
signatures. Defaults to yes.
With @option{--list-sigs} and @option{--check-sigs} sort the
signatures by keyID and creation time to make it easier to view the
history of these signatures. The self-signature is also listed
before other signatures. Defaults to yes.
@end table
@ -1514,12 +1541,12 @@ the opposite meaning. The options are:
@itemx --disable-large-rsa
@opindex enable-large-rsa
@opindex disable-large-rsa
With --generate-key and --batch, enable the creation of RSA secret keys as
large as 8192 bit. Note: 8192 bit is more than is generally
recommended. These large keys don't significantly improve security,
but they are more expensive to use, and their signatures and
certifications are larger. This option is only available if the
binary was build with large-secmem support.
With @option{--generate-key} and @option{--batch}, enable the creation
of RSA secret keys as large as 8192 bit. Note: 8192 bit is more than
is generally recommended. These large keys don't significantly
improve security, but they are more expensive to use, and their
signatures and certifications are larger. This option is only
available if the binary was build with large-secmem support.
@item --enable-dsa2
@itemx --disable-dsa2
@ -1537,9 +1564,9 @@ will be expanded to a filename containing the photo. "%I" does the
same, except the file will not be deleted once the viewer exits.
Other flags are "%k" for the key ID, "%K" for the long key ID, "%f"
for the key fingerprint, "%t" for the extension of the image type
(e.g. "jpg"), "%T" for the MIME type of the image (e.g. "image/jpeg"),
(e.g., "jpg"), "%T" for the MIME type of the image (e.g., "image/jpeg"),
"%v" for the single-character calculated validity of the image being
viewed (e.g. "f"), "%V" for the calculated validity as a string (e.g.
viewed (e.g., "f"), "%V" for the calculated validity as a string (e.g.,
"full"), "%U" for a base32 encoded hash of the user ID,
and "%%" for an actual percent sign. If neither %i or %I are present,
then the photo will be supplied to the viewer on standard input.
@ -1773,7 +1800,9 @@ useful if you don't want to keep your secret keys (or one of them)
online but still want to be able to check the validity of a given
recipient's or signator's key. If the given key is not locally
available but an LDAP keyserver is configured the missing key is
imported from that server.
imported from that server. The value "none" is explicitly allowed to
distinguish between the use of any trusted-key option and no use of
this option at all (e.g. due to the @option{--no-options} option).
@item --add-desig-revoker [sensitive:]@var{fingerprint}
@opindex add-desig-revoker
@ -1914,6 +1943,29 @@ is guaranteed to return with an exit code of 0 if and only if a
signature has been encountered, is valid, and the key matches one of
the fingerprints given by this option.
@item --assert-pubkey-algo @var{algolist}
@opindex assert-pubkey-algo
During data signature verification this options checks whether the
used public key algorithm matches the algorithms given by
@var{algolist}. This option can be given multiple times to
concatenate more algorithms to the list; the delimiter of the list are
either commas or spaces.
The algorithm names given in the list may either be verbatim names
like "ed25519" with an optional leading single equal sign, or being
prefixed with ">", ">=", "<=", or "<". That prefix operator is
applied to the number part of the algorithm name; for example 2048 in
"rsa2048" or 384 in "brainpoolP384r1". If the the leading non-digits
in the name matches, the prefix operator is used to compare the number
part, a trailing suffix is ignored in this case. For example an
algorithm list ">rsa3000, >=brainpool384r1, =ed25519" allows RSA
signatures with more that 3000 bits, Brainpool curves 384 and 512,
and the ed25519 algorithm.
With this option gpg (and also gpgv) is guaranteed to return with an
exit code of 0 if and only if all valid signatures on data are made
using a matching algorithm from the given list.
@item --auto-key-locate @var{mechanisms}
@itemx --no-auto-key-locate
@ -1947,20 +1999,20 @@ list. The default is "local,wkd".
@item ntds
Locate the key using the Active Directory (Windows only). This
method also allows to search by fingerprint using the command
method also allows one to search by fingerprint using the command
@option{--locate-external-key}. Note that this mechanism is
actually a shortcut for the mechanism @samp{keyserver} but using
"ldap:///" as the keyserver.
@item keyserver
Locate a key using a keyserver. This method also allows to search
Locate a key using a keyserver. This method also allows one to search
by fingerprint using the command @option{--locate-external-key} if
any of the configured keyservers is an LDAP server.
@item keyserver-URL
In addition, a keyserver URL as used in the @command{dirmngr}
configuration may be used here to query that particular keyserver.
This method also allows to search by fingerprint using the command
This method also allows one to search by fingerprint using the command
@option{--locate-external-key} if the URL specifies an LDAP server.
@item local
@ -2018,7 +2070,7 @@ default), that keyserver is tried. Note that the creator of the
signature uses the option @option{--sig-keyserver-url} to specify the
preferred keyserver for data signatures.
3. If the signature has the Signer's UID set (e.g. using
3. If the signature has the Signer's UID set (e.g., using
@option{--sender} while creating the signature) a Web Key Directory
(WKD) lookup is done. This is the default configuration but can be
disabled by removing WKD from the auto-key-locate list or by using the
@ -2046,7 +2098,7 @@ option is ignored if the option @option{--with-colons} is used.
@item --keyserver @var{name}
@opindex keyserver
This option is deprecated - please use the @option{--keyserver} in
This option is deprecated --- please use the @option{--keyserver} in
@file{dirmngr.conf} instead.
Use @var{name} as your keyserver. This is the server that
@ -2266,7 +2318,7 @@ suppressed on the command line.
@itemx --no-require-secmem
@opindex require-secmem
Refuse to run if GnuPG cannot get secure memory. Defaults to no
(i.e. run, but give a warning).
(i.e., run, but give a warning).
@item --require-cross-certification
@ -2336,19 +2388,21 @@ the key in this file is fully valid.
@opindex encrypt-to
Same as @option{--recipient} but this one is intended for use in the
options file and may be used with your own user-id as an
"encrypt-to-self". These keys are only used when there are other
recipients given either by use of @option{--recipient} or by the asked
user id. No trust checking is performed for these user ids and even
disabled keys can be used.
"encrypt-to-self". It is suggested to use a fingerprint or at least a
long keyID for @var{name}. These keys are only used when there are
other recipients given either by use of @option{--recipient} or by the
asked user id. No trust checking is performed for these user ids and
even disabled keys can be used.
@item --hidden-encrypt-to @var{name}
@opindex hidden-encrypt-to
Same as @option{--hidden-recipient} but this one is intended for use in the
options file and may be used with your own user-id as a hidden
"encrypt-to-self". These keys are only used when there are other
recipients given either by use of @option{--recipient} or by the asked user id.
No trust checking is performed for these user ids and even disabled
keys can be used.
Same as @option{--hidden-recipient} but this one is intended for use
in the options file and may be used with your own user-id as a hidden
"encrypt-to-self". It is suggested to use a fingerprint or at least a
long keyID for @var{name}. These keys are only used when there are
other recipients given either by use of @option{--recipient} or by the
asked user id. No trust checking is performed for these user ids and
even disabled keys can be used.
@item --no-encrypt-to
@opindex no-encrypt-to
@ -2396,7 +2450,7 @@ id used to make the signature and embeds that user ID into the created
signature (using OpenPGP's ``Signer's User ID'' subpacket). If the
option is given multiple times a suitable user ID is picked. However,
if the signing key was specified directly by using a mail address
(i.e. not by using a fingerprint or key ID) this option is used and
(i.e., not by using a fingerprint or key ID) this option is used and
the mail address is embedded in the created signature.
When verifying a signature @var{mbox} is used to restrict the
@ -2505,7 +2559,7 @@ the @option{--status-fd} line ``PROGRESS'' to provide a value for
@item --key-origin @var{string}[,@var{url}]
@opindex key-origin
gpg can track the origin of a key. Certain origins are implicitly
known (e.g. keyserver, web key directory) and set. For a standard
known (e.g., keyserver, web key directory) and set. For a standard
import the origin of the keys imported can be set with this option.
To list the possible values use "help" for @var{string}. Some origins
can store an optional @var{url} argument. That URL can appended to
@ -2627,12 +2681,12 @@ The available filter types are:
@item drop-subkey
This filter drops the selected subkeys.
Currently only implemented for --export-filter.
Currently only implemented for @option{--export-filter}.
@item drop-sig
This filter drops the selected key signatures on user ids.
Self-signatures are not considered.
Currently only implemented for --import-filter.
Currently only implemented for @option{--import-filter}.
@item select
This filter is only implemented by @option{--list-filter}. All
@ -2677,13 +2731,13 @@ The available properties are:
@itemx key_created_d
The first is the timestamp a public key or subkey packet was
created. The second is the same but given as an ISO string,
e.g. "2016-08-17". (drop-subkey)
e.g., "2016-08-17". (drop-subkey)
@item key_expires
@itemx key_expires_d
The expiration time of a public key or subkey or 0 if it does not
expire. The second is the same but given as an ISO date string or
an empty string e.g. "2038-01-19".
an empty string e.g., "2038-01-19".
@item fpr
The hexified fingerprint of the current subkey or primary key.
@ -2716,7 +2770,7 @@ The available properties are:
@itemx sig_created_d
The first is the timestamp a signature packet was created. The
second is the same but given as an ISO date string,
e.g. "2016-08-17". (drop-sig)
e.g., "2016-08-17". (drop-sig)
@item sig_expires
@itemx sig_expires_d
@ -2842,7 +2896,7 @@ obsolete; it does not harm to use it though.
@opindex legacy-list-mode
Revert to the pre-2.1 public key list mode. This only affects the
human readable output and not the machine interface
(i.e. @code{--with-colons}). Note that the legacy format does not
(i.e., @code{--with-colons}). Note that the legacy format does not
convey suitable information for elliptic curves.
@item --with-fingerprint
@ -2851,12 +2905,15 @@ Same as the command @option{--fingerprint} but changes only the format
of the output and may be used together with another command.
@item --with-subkey-fingerprint
@itemx --without-subkey-fingerprint
@opindex with-subkey-fingerprint
@opindex without-subkey-fingerprint
If a fingerprint is printed for the primary key, this option forces
printing of the fingerprint for all subkeys. This could also be
achieved by using the @option{--with-fingerprint} twice but by using
this option along with keyid-format "none" a compact fingerprint is
printed.
this option along with the default keyid-format "none" a compact
fingerprint is printed. Since version 2.6.0 this option is active by
default; use the ``without'' variant to disable it.
@item --with-v5-fingerprint
@opindex with-v5-fingerprint
@ -2899,24 +2956,6 @@ done with @code{--with-colons}.
@table @gnupgtabopt
@item -t, --textmode
@itemx --no-textmode
@opindex textmode
Treat input files as text and store them in the OpenPGP canonical text
form with standard "CRLF" line endings. This also sets the necessary
flags to inform the recipient that the encrypted or signed data is text
and may need its line endings converted back to whatever the local
system uses. This option is useful when communicating between two
platforms that have different line ending conventions (UNIX-like to Mac,
Mac to Windows, etc). @option{--no-textmode} disables this option, and
is the default.
@item --force-v3-sigs
@itemx --no-force-v3-sigs
@item --force-v4-certs
@itemx --no-force-v4-certs
These options are obsolete and have no effect since GnuPG 2.1.
@item --force-ocb
@itemx --force-aead
@opindex force-ocb
@ -2978,7 +3017,7 @@ to safely override the algorithm chosen by the recipient key
preferences, as GPG will only select an algorithm that is usable by
all recipients. The most highly ranked digest algorithm in this list
is also used when signing without encryption
(e.g. @option{--clear-sign} or @option{--sign}).
(e.g., @option{--clear-sign} or @option{--sign}).
@item --personal-compress-preferences @var{string}
@opindex personal-compress-preferences
@ -2989,7 +3028,7 @@ allows the user to safely override the algorithm chosen by the
recipient key preferences, as GPG will only select an algorithm that
is usable by all recipients. The most highly ranked compression
algorithm in this list is also used when there are no recipient keys
to consider (e.g. @option{--symmetric}).
to consider (e.g., @option{--symmetric}).
@item --s2k-cipher-algo @var{name}
@opindex s2k-cipher-algo
@ -3015,7 +3054,7 @@ of times (see @option{--s2k-count}).
Specify how many times the passphrases mangling for symmetric
encryption is repeated. This value may range between 1024 and
65011712 inclusive. The default is inquired from gpg-agent. Note
that not all values in the 1024-65011712 range are legal and if an
that not all values in the 1024--65011712 range are legal and if an
illegal value is selected, GnuPG will round up to the nearest legal
value. This option is only meaningful if @option{--s2k-mode} is set
to the default of 3.
@ -3107,6 +3146,15 @@ This option adjusts the compliance mode "de-vs" for stricter key size
requirements. For example, a value of 3000 turns rsa2048 and dsa2048
keys into non-VS-NfD compliant keys.
@item --require-pqc-encryption
@opindex require-pqc-encryption
This option forces the use of quantum-resistant encryption algorithms.
If not all public keys are quantum-resistant the encryption will fail.
On decryption a warning is printed for all non-quantum-resistant keys.
As of now the Kyber (ML-KEM768 and ML-KEM1024) algorithms are
considered quantum-resistant; Kyber is always used in a composite
scheme along with a classic ECC algorithm.
@item --require-compliance
@opindex require-compliance
To check that data has been encrypted according to the rules of the
@ -3151,7 +3199,7 @@ Prompt before overwriting any files.
Set compatibility flags to work around problems due to non-compliant
keys or data. The @var{flags} are given as a comma separated
list of flag names and are OR-ed together. The special flag "none"
clears the list and allows to start over with an empty list. To get a
clears the list and allows one to start over with an empty list. To get a
list of available flags the sole word "help" can be used.
@item --debug-level @var{level}
@ -3185,7 +3233,7 @@ however carefully selected to best aid in debugging.
@item --debug @var{flags}
@opindex debug
Set debug flags. All flags are or-ed and @var{flags} may be given
in C syntax (e.g. 0x0042) or as a comma separated list of flag names.
in C syntax (e.g., 0x0042) or as a comma separated list of flag names.
To get a list of all supported flags the single word "help" can be
used. This option is only useful for debugging and the behavior may
change at any time without notice.
@ -3207,7 +3255,7 @@ and may thus be changed or removed at any time without notice.
@item --debug-allow-large-chunks
@opindex debug-allow-large-chunks
To facilitate software tests and experiments this option allows to
To facilitate software tests and experiments this option allows one to
specify a limit of up to 4 EiB (@code{--chunk-size 62}).
@item --debug-ignore-expiration
@ -3220,7 +3268,7 @@ only useful for certain regression tests.
This option is only useful for testing; it sets the system time back
or forth to @var{epoch} which is the number of seconds elapsed since
the year 1970. Alternatively @var{epoch} may be given as a full ISO
time string (e.g. "20070924T154812").
time string (e.g., "20070924T154812").
If you suffix @var{epoch} with an exclamation mark (!), the system time
will appear to be frozen at the specified time.
@ -3378,9 +3426,23 @@ to display the message. This option overrides @option{--set-filename}.
@itemx --no-use-embedded-filename
@opindex use-embedded-filename
Try to create a file with a name as embedded in the data. This can be
a dangerous option as it enables overwriting files. Defaults to no.
a dangerous option as it enables overwriting files by giving the
sender control on how to store files. Defaults to no.
Note that the option @option{--output} overrides this option.
A better approach than using this option is to decrypt to a temporary
filename and then rename that file to the embedded file name after
checking that the embedded filename is harmless. When using the
@option{--status-fd} option gpg tells the filename as part of the
PLAINTEXT status message. If the filename is important, the use of
@command{gpgtar} is another option because gpgtar will never overwrite
a file but decrypt the files to a new directory.
Note also that unless a modern version 5 signature is used the
embedded filename is not part of the signed data.
@item --cipher-algo @var{name}
@opindex cipher-algo
Use @var{name} as cipher algorithm. Running the program with the
@ -3546,7 +3608,7 @@ are:
@opindex no-symkey-cache
Disable the passphrase cache used for symmetrical en- and decryption.
This cache is based on the message specific salt value
(cf. @option{--s2k-mode}).
(cf.@: @option{--s2k-mode}).
@item --request-origin @var{origin}
@opindex request-origin
@ -3646,7 +3708,7 @@ not need to be listed explicitly.
@opindex allow-weak-key-signatures
To avoid a minor risk of collision attacks on third-party key
signatures made using SHA-1, those key signatures are considered
invalid. This options allows to override this restriction.
invalid. This options allows one to override this restriction.
@item --override-compliance-check
This was a temporary introduced option and has no more effect.
@ -3818,6 +3880,12 @@ This option enables a mode in which filenames of the form
@file{-&n}, where n is a non-negative decimal number,
refer to the file descriptor n and not to a file with that name.
@item --disable-fd-translation
@opindex disable-fd-translation
This option changes the behaviour for all following options to expect
libc file descriptors instead of HANDLE values on the command line.
The option has an effect only on Windows.
@item --no-expensive-trust-checks
@opindex no-expensive-trust-checks
Experimental use only.
@ -3891,6 +3959,25 @@ all on Windows.
@table @gnupgtabopt
@item -t, --textmode
@itemx --no-textmode
@opindex textmode
Treat input files as text and store them in the OpenPGP canonical text
form with standard "CRLF" line endings. This also sets the necessary
flags to inform the recipient that the encrypted or signed data is text
and may need its line endings converted back to whatever the local
system uses. This option was useful when communicating between two
platforms with different line ending conventions (UNIX-like to Mac,
Mac to Windows, etc). @option{--no-textmode} disables this option, and
is the default. Note that this is a legacy option which should not
anymore be used by any modern software.
@item --force-v3-sigs
@itemx --no-force-v3-sigs
@item --force-v4-certs
@itemx --no-force-v4-certs
These options are obsolete and have no effect since GnuPG 2.1.
@item --show-photos
@itemx --no-show-photos
@opindex show-photos
@ -4111,7 +4198,7 @@ Operation is further controlled by a few environment variables:
@item GNUPG_EXEC_DEBUG_FLAGS
@efindex GNUPG_EXEC_DEBUG_FLAGS
This variable allows to enable diagnostics for process management.
This variable allows one to enable diagnostics for process management.
A numeric decimal value is expected. Bit 0 enables general
diagnostics, bit 1 enables certain warnings on Windows.
@ -4615,7 +4702,7 @@ If you don't give any of them, no user ID is created.
@item Expire-Date: @var{iso-date}|(@var{number}[d|w|m|y])
Set the expiration date for the key (and the subkey). It may either
be entered in ISO date format (e.g. "20000815T145012") or as number of
be entered in ISO date format (e.g., "20000815T145012") or as number of
days, weeks, month or years after the creation date. The special
notation "seconds=N" is also allowed to specify a number of seconds
since creation. Without a letter days are assumed. Note that there

View File

@ -136,7 +136,7 @@ Run in server mode and wait for commands on the @code{stdin}.
Behave as a Dirmngr client issuing the request @var{command} with the
optional list of @var{args}. The output of the Dirmngr is printed
stdout. Please note that file names given as arguments should have an
absolute file name (i.e. commencing with @code{/}) because they are
absolute file name (i.e., commencing with @code{/}) because they are
passed verbatim to the Dirmngr and the working directory of the
Dirmngr might not be the same as the one of this client. Currently it
is not possible to pass data via stdin to the Dirmngr. @var{command}
@ -259,7 +259,7 @@ optional @var{pattern}. Those pattern consist of a list of user ids
@option{--armor} option a few informational lines are prepended before
each block. There is one limitation: As there is no commonly agreed
upon way to pack more than one certificate into an ASN.1 structure,
the binary export (i.e. without using @option{armor}) works only for
the binary export (i.e., without using @option{armor}) works only for
the export of one certificate. Thus it is required to specify a
@var{pattern} which yields exactly one certificate. Ephemeral
certificate are only exported if all @var{pattern} are given as
@ -462,7 +462,7 @@ line of the @file{trustlist.txt}
@opindex force-crl-refresh
Tell the dirmngr to reload the CRL for each request. For better
performance, the dirmngr will actually optimize this by suppressing
the loading for short time intervals (e.g. 30 minutes). This option
the loading for short time intervals (e.g., 30 minutes). This option
is useful to make sure that a fresh CRL is available for certificates
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
@ -539,7 +539,7 @@ Create PEM encoded output. Default is binary output.
@item --base64
@opindex base64
Create Base-64 encoded output; i.e. PEM without the header lines.
Create Base-64 encoded output; i.e., PEM without the header lines.
@item --assume-armor
@opindex assume-armor
@ -639,11 +639,11 @@ done with @code{--with-colons}.
@item --no-pretty-dn
@opindex no-pretty-dn
By default gpgsm prints distinguished names (DNs) like the Issuer or
Subject in a more readable format (e.g. using a well defined order of
Subject in a more readable format (e.g., using a well defined order of
the parts). However, this format can't be used as input strings.
This option reverts printing to standard RFC-2253 format and thus
avoids the need to use --dump-cert or --with-colons to get the
``real'' name.
avoids the need to use @option{--dump-cert} or @option{--with-colons}
to get the ``real'' name.
@end table
@ -754,7 +754,7 @@ key database clear of unneeded certificates stored on smartcards.
This option is only useful for testing; it sets the system time back or
forth to @var{epoch} which is the number of seconds elapsed since the year
1970. Alternatively @var{epoch} may be given as a full ISO time string
(e.g. "20070924T154812").
(e.g., "20070924T154812").
@item --with-ephemeral-keys
@opindex with-ephemeral-keys
@ -767,9 +767,21 @@ is given as fingerprint or keygrip.
Set compatibility flags to work around problems due to non-compliant
certificates or data. The @var{flags} are given as a comma separated
list of flag names and are OR-ed together. The special flag "none"
clears the list and allows to start over with an empty list. To get a
clears the list and allows one to start over with an empty list. To get a
list of available flags the sole word "help" can be used.
@item --enable-special-filenames
@opindex enable-special-filenames
This option enables a mode in which filenames of the form
@file{-&n}, where n is a non-negative decimal number,
refer to the file descriptor n and not to a file with that name.
@item --disable-fd-translation
@opindex disable-fd-translation
This option changes the behaviour for all following options to expect
libc file descriptors instead of HANDLE values on the command line.
The option has an effect only on Windows.
@item --debug-level @var{level}
@opindex debug-level
Select the debug level for investigating problems. @var{level} may be
@ -801,7 +813,7 @@ however carefully selected to best aid in debugging.
@item --debug @var{flags}
@opindex debug
Set debug flags. All flags are or-ed and @var{flags} may be given
in C syntax (e.g. 0x0042) or as a comma separated list of flag names.
in C syntax (e.g., 0x0042) or as a comma separated list of flag names.
To get a list of all supported flags the single word "help" can be
used. This option is only useful for debugging and the behavior may
change at any time without notice.
@ -974,9 +986,9 @@ This is plain text file with a few help entries used with
@command{gpg} and @command{gpgsm}. The standard file has English help
texts; to install localized versions use filenames like @file{help.LL.txt}
with LL denoting the locale. GnuPG comes with a set of predefined help
files in the data directory (e.g. @file{@value{DATADIR}/gnupg/help.de.txt})
files in the data directory (e.g., @file{@value{DATADIR}/gnupg/help.de.txt})
and allows overriding of any help item by help files stored in the
system configuration directory (e.g. @file{@value{SYSCONFDIR}/help.de.txt}).
system configuration directory (e.g., @file{@value{SYSCONFDIR}/help.de.txt}).
For a reference of the help file's syntax, please see the installed
@file{help.txt} file.
@ -987,11 +999,10 @@ This file is a collection of common certificates used to populated a
newly created @file{pubring.kbx}. An administrator may replace this
file with a custom one. The format is a concatenation of PEM encoded
X.509 certificates. This global file is installed in the data directory
(e.g. @file{@value{DATADIR}/com-certs.pem}).
(e.g., @file{@value{DATADIR}/com-certs.pem}).
@end table
@c man:.RE
Note that on larger installations, it is useful to put predefined files
into the directory @file{/etc/skel/.gnupg/} so that newly created users
start up with a working configuration. For existing users a small
@ -1100,7 +1111,7 @@ of a transfer error, a program error or tampering with the message).
@end table
@item Error verifying a signature
For some reason the signature could not be verified, i.e. it cannot be
For some reason the signature could not be verified, i.e., it cannot be
decided whether the signature is valid or invalid. A common reason for
this is a missing certificate.
@ -1281,7 +1292,7 @@ provides a regular command line interface which exhibits a full client
to this protocol (but uses internal linking). To start
@command{gpgsm} as a server the command line the option
@code{--server} must be used. Additional options are provided to
select the communication method (i.e. the name of the socket).
select the communication method (i.e., the name of the socket).
We assume that the connection has already been established; see the
Assuan manual for details.
@ -1345,7 +1356,7 @@ correct.
OUTPUT FD[=@var{n}] [--armor|--base64]
@end example
Set the file descriptor to be used for the output (i.e. the encrypted
Set the file descriptor to be used for the output (i.e., the encrypted
message). Obviously the pipe must be open at that point, the server
establishes its own end. If the server returns an error the client
should consider this session failed.
@ -1388,11 +1399,11 @@ The decryption is done by using the command
DECRYPT
@end example
It performs the decrypt operation after doing some check on the internal
state (e.g. that all needed data has been set). Because it utilizes
the GPG-Agent for the session key decryption, there is no need to ask
the client for a protecting passphrase - GpgAgent takes care of this by
requesting this from the user.
It performs the decrypt operation after doing some check on the
internal state (e.g., that all needed data has been set). Because it
utilizes the GPG-Agent for the session key decryption, there is no
need to ask the client for a protecting passphrase --- GpgAgent takes
care of this by requesting this from the user.
@node GPGSM SIGN

View File

@ -91,7 +91,7 @@ Add @var{file} to the list of keyrings.
If @var{file} begins with a tilde and a slash, these
are replaced by the HOME directory. If the filename
does not contain a slash, it is assumed to be in the
home-directory ("~/.gnupg" if --homedir is not used).
home-directory ("~/.gnupg" if @option{--homedir} is not used).
@item --output @var{file}
@itemx -o @var{file}
@ -140,6 +140,10 @@ This option enables a mode in which filenames of the form
@file{-&n}, where n is a non-negative decimal number,
refer to the file descriptor n and not to a file with that name.
@item --assert-pubkey-algo @var{algolist}
@opindex assert-pubkey-algo
This option works in the same way as described for @command{gpg}.
@end table
@mansect return value
@ -180,14 +184,21 @@ If set directory used instead of "~/.gnupg".
@mansect files
@subsection FILES
@table @asis
Default keyring file is expected in the GnuPG home directory
(@pxref{option --homedir}, @code{GNUPGHOME}).
@table @file
@item ~/.gnupg/trustedkeys.kbx
@efindex trustedkeys.kbx
The default keyring with the allowed keys, using the new keybox format.
@item ~/.gnupg/trustedkeys.gpg
The default keyring with the allowed keys.
@efindex trustedkeys.gpg
When @file{trustedkeys.kbx} is not available, the default keyring with
the allowed keys, using a legacy format.
@end table
@mansect see also
@command{gpg}(1)
@include see-also-note.texi

View File

@ -80,7 +80,7 @@ would anyway ignore such a request. Thus just hit enter.
If you want to create a client certificate for email encryption, this
would be the place to enter your mail address
(e.g. @email{joe@@example.org}). You may enter as many addresses as you like,
(e.g., @email{joe@@example.org}). You may enter as many addresses as you like,
however the CA may not accept them all or reject the entire request.
@cartouche

View File

@ -59,7 +59,7 @@ A name must start with a letter and end with a colon. Valid
characters are all ASCII letters, numbers and the hyphen. Comparison
of names is done case insensitively. Names may be used several times
to represent an array of values. Note that the name "Key" is special
in that it is madandory must occur only once.
in that it is mandatory and must occur only once.
*** Values
Values are UTF-8 encoded strings. Values can be wrapped at any point,
@ -156,7 +156,7 @@ dialog window when card is not available. When the value is "no", a
card operation is refused with GPG_ERR_UNUSABLE_SECKEY error.
*** Backup-info
This gives information for a backup of the key. The follwoing fields
This gives information for a backup of the key. The following fields
are space delimited:
- Hexified keygrip (uppercase) to make it easy to identify the
@ -345,7 +345,7 @@ The currently defined protection modes are:
** Shadowed Private Key Format
To keep track of keys stored on IC cards we use a third format for
private kyes which are called shadow keys as they are only a reference
private keys which are called shadow keys as they are only a reference
to keys stored on a token:
(shadowed-private-key
@ -395,7 +395,7 @@ This format is used to transfer keys between gpg and gpg-agent.
* PUBKEYALGO is a Libgcrypt algo name
* CURVENAME is the name of the curve - only used with ECC.
* P1 .. PN are the parameters; the public parameters are never encrypted
the secrect key parameters are encrypted if the "protection" list is
the secret key parameters are encrypted if the "protection" list is
given. To make this more explicit each parameter is preceded by a
flag "_" for cleartext or "e" for encrypted text.
* CSUM is the deprecated 16 bit checksum as defined by OpenPGP. This
@ -404,7 +404,7 @@ This format is used to transfer keys between gpg and gpg-agent.
the old 16 bit checksum (above) is used and if it is "none" no
protection at all is used.
* PROTALGO is a Libgcrypt style cipher algorithm name
* IV is the initialization verctor.
* IV is the initialization vector.
* S2KMODE is the value from RFC-4880.
* S2KHASH is a libgcrypt style hash algorithm identifier.
* S2KSALT is the 8 byte salt
@ -492,7 +492,7 @@ with "encrypted_octet_string" decoding to:
(hash sha1 #0102030405060708091011121314151617181920#)
)
To compute the hash this S-expression (in canoncical format) was
To compute the hash this S-expression (in canonical format) was
hashed:
((desc "List of system passphrases")

View File

@ -161,7 +161,7 @@ helpers to debug problems.
@item --debug @var{flags}
@opindex debug
Set debug flags. All flags are or-ed and @var{flags} may be given
in C syntax (e.g. 0x0042) or as a comma separated list of flag names.
in C syntax (e.g., 0x0042) or as a comma separated list of flag names.
To get a list of all supported flags the single word "help" can be
used. This option is only useful for debugging and the behavior may
change at any time without notice.
@ -238,7 +238,7 @@ this option only if you know what you are doing.
Use @var{library} to access the smartcard reader. The current default
on Unix is @file{libpcsclite.so} and on Windows @file{winscard.dll}.
Instead of using this option you might also want to install a symbolic
link to the default file name (e.g. from @file{libpcsclite.so.1}).
link to the default file name (e.g., from @file{libpcsclite.so.1}).
A Unicode file name may not be used on Windows.
@item --disable-ccid
@ -309,7 +309,7 @@ with lower priority should be used by default.
@item --application-priority @var{namelist}
@opindex application-priority
This option allows to change the order in which applications of a card
This option allows one to change the order in which applications of a card
a tried if no specific application was requested. @var{namelist} is a
space or comma delimited list of application names. Unknown names are
simply skipped. Applications not mentioned in the list are put in the
@ -503,7 +503,7 @@ will return an error when a card change has been detected and the use of
this function is therefore required.
Background: We want to keep the client clear of handling card changes
between operations; i.e. the client can assume that all operations are
between operations; i.e., the client can assume that all operations are
done on the same card unless he call this function.
@example
@ -717,7 +717,7 @@ reset the card.
This is used by gpg-agent to reuse a primary pipe connection and
may be used by clients to backup from a conflict in the serial
command; i.e. to select another application.
command; i.e., to select another application.

View File

@ -39,7 +39,7 @@ using the option @option{--with-colons}.
@item By fingerprint.
This format is deduced from the length of the string and its content or
the @code{0x} prefix. Note, that only the 20 byte version fingerprint
is available with @command{gpgsm} (i.e. the SHA-1 hash of the
is available with @command{gpgsm} (i.e., the SHA-1 hash of the
certificate).
When using @command{gpg} an exclamation mark (!) may be appended to
@ -88,7 +88,7 @@ with left and right angles.
@item By partial match on an email address.
This is indicated by prefixing the search string with an @code{@@}.
This uses a substring search but considers only the mail address
(i.e. inside the angle brackets).
(i.e., inside the angle brackets).
@cartouche
@example

View File

@ -124,7 +124,7 @@ $ watchgnupg --time-only
@end example
This waits for connections on the local socket
(e.g. @file{/var/run/user/1234/gnupg/S.log}) and shows all log
(e.g., @file{/var/run/user/1234/gnupg/S.log}) and shows all log
entries. To make this work the option @option{log-file} needs to be
used with all modules which logs are to be shown. The suggested entry
for the configuration files is:
@ -133,8 +133,8 @@ for the configuration files is:
log-file socket://
@end example
If the default socket as given above and returned by "echo $(gpgconf
--list-dirs socketdir)/S.log" is not desired an arbitrary socket name
If the default socket as given above and returned by @code{"echo $(gpgconf
--list-dirs socketdir)/S.log"} is not desired an arbitrary socket name
can be specified, for example @file{socket:///home/foo/bar/mysocket}.
For debugging purposes it is also possible to do remote logging. Take
care if you use this feature because the information is send in the
@ -400,7 +400,7 @@ expected in the current GnuPG home directory. This command is usually
not required because GnuPG is able to detect and remove stale lock
files. Before using the command make sure that the file protected by
the lock file is actually not in use. The lock command may be used to
lock an accidently removed lock file. Note that the commands have no
lock an accidentally removed lock file. Note that the commands have no
effect on Windows because the mere existence of a lock file does not
mean that the lock is active.
@ -1151,13 +1151,21 @@ More fields may be added in future to the output.
Under Windows this file is used to install GnuPG as a portable
application. An empty file named @file{gpgconf.ctl} is expected in
the same directory as the tool @file{gpgconf.exe}. The root of the
the same directory as the tool @file{gpgconf.exe} or the file must
have a keyword @code{portable} with the value true. The root of the
installation is then that directory; or, if @file{gpgconf.exe} has
been installed directly below a directory named @file{bin}, its parent
directory. You also need to make sure that the following directories
exist and are writable: @file{ROOT/home} for the GnuPG home and
@file{ROOT@value{LOCALCACHEDIR}} for internal cache files.
On both platforms the keyword @code{gnupg} can be used to change the
standard home directory. For example a value of "gnupg-vsd" will
change the default home directory on unix from @file{~/.gnupg} to
@file{~/.gnupg-vsd}. The socket directory is changed accordingly
unless the @code{socketdir} keyword has been used. On Windows the
Registry keys are modified as well.
@item /etc/gnupg/gpgconf.conf
@cindex gpgconf.conf
@ -1284,7 +1292,7 @@ Alternatively an arbitrary string may be used to identify a
passphrase; it is suggested that such a string is prefixed with the
name of the application (e.g @code{foo:12346}). Scripts should always
use the option @option{--with-colons}, which provides the keygrip in a
"grp" line (cf. @file{doc/DETAILS})/
"grp" line (cf.@: @file{doc/DETAILS})/
@noindent
One of the following command options must be given:
@ -1765,7 +1773,7 @@ The return value of this command is
@table @code
@item 0
The certificate under question is valid; i.e. there is a valid CRL
The certificate under question is valid; i.e., there is a valid CRL
available and it is not listed there or the OCSP request returned that
that certificate is valid.
@ -2088,9 +2096,9 @@ This option is deprecated in favor of option @option{--directory}.
@item --no-compress
@opindex no-compress
This option tells gpg to disable compression (i.e. using option -z0).
This option tells gpg to disable compression (i.e., using option -z0).
It is useful for archiving only large files which are are already
compressed (e.g. a set of videos).
compressed (e.g., a set of videos).
@item --gpg @var{gpgcmd}
@opindex gpg
@ -2103,9 +2111,10 @@ Pass the specified extra options to @command{gpg}.
@item --tar-args @var{args}
@opindex tar-args
Assume @var{args} are standard options of the command @command{tar}
and parse them. The only supported tar options are "--directory",
"--files-from", and "--null" This is an obsolete options because those
supported tar options can also be given directly.
and parse them. The only supported tar options are
@option{--directory}, @option{--files-from}, and @option{--null}.
This is an obsolete options because those supported tar options can
also be given directly.
@item --tar @var{command}
@opindex tar

View File

@ -136,6 +136,8 @@ The command @option{--print-wkd-url} prints the URLs used to fetch the
key for the given user-ids from WKD. The meanwhile preferred format
with sub-domains is used here.
All commands may also be given without the two leading dashes.
@mansect options
@noindent
@command{gpg-wks-client} understands these options:
@ -212,7 +214,7 @@ The default is @file{openpgpkey}.
@opindex blacklist
This option is used to exclude certain mail addresses from a mirror
operation. The format of @var{file} is one mail address (just the
addrspec, e.g. "postel@@isi.edu") per line. Empty lines and lines
addrspec, e.g., "postel@@isi.edu") per line. Empty lines and lines
starting with a '#' are ignored.
@item --add-revocs

View File

@ -183,7 +183,7 @@ gpgv_LDFLAGS =
t_common_ldadd =
module_tests = t-rmd160 t-keydb t-keydb-get-keyblock t-stutter
module_tests = t-rmd160 t-keydb t-keydb-get-keyblock t-stutter t-keyid
t_rmd160_SOURCES = t-rmd160.c rmd160.c
t_rmd160_LDADD = $(t_common_ldadd)
t_keydb_SOURCES = t-keydb.c test-stubs.c $(common_source)
@ -200,6 +200,10 @@ t_stutter_SOURCES = t-stutter.c test-stubs.c \
t_stutter_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
t_keyid_SOURCES = t-keyid.c test-stubs.c $(common_source)
t_keyid_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
$(PROGRAMS): $(needed_libs) ../common/libgpgrl.a

View File

@ -1031,10 +1031,10 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
checkcrc++;
break;
}
else if (afx->dearmor_state && c == '-'
else if (c == '-'
&& afx->buffer_pos + 8 < afx->buffer_len
&& !strncmp (afx->buffer, "-----END ", 8)) {
break; /* End in --dearmor mode. */
break; /* End in --dearmor mode or No CRC. */
}
else {
log_error(_("invalid radix64 character %02X skipped\n"), c);

View File

@ -306,7 +306,9 @@ gpg_mpi_write (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten)
p = gcry_mpi_get_opaque (a, &nbits);
if (p)
{
/* Strip leading zero bits. */
/* First get nbits back to full bytes. */
nbits = ((nbits + 7) / 8) * 8;
/* Then strip leading zero bits. */
for (; nbits >= 8 && !*p; p++, nbits -= 8)
;
if (nbits >= 8 && !(*p & 0x80))
@ -431,7 +433,7 @@ sos_write (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten)
* Write an opaque string to the output stream without length info.
*/
gpg_error_t
gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a)
gpg_mpi_write_opaque_nohdr (iobuf_t out, gcry_mpi_t a)
{
int rc;
@ -450,6 +452,45 @@ gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a)
}
/*
* Write an opaque MPI string with a four-byte octet count to the
* output stream. If R_NWRITTEN is not NULL the number of written
* bytes is stored there. OUT may be NULL in which case only
* R_NWRITTEN is updated and error checking is done.
*/
gpg_error_t
gpg_mpi_write_opaque_32 (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten)
{
gpg_error_t err;
if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
{
unsigned int nbits, nbytes;
const void *p;
p = gcry_mpi_get_opaque (a, &nbits);
nbytes = (nbits + 7)/8;
if (out)
{
write_32 (out, nbytes);
err = p ? iobuf_write (out, p, nbytes) : 0;
}
else
err = 0;
if (r_nwritten)
*r_nwritten = 4 + (p? nbytes : 0);
}
else
{
err = gpg_error (GPG_ERR_BAD_MPI);
if (r_nwritten)
*r_nwritten = 0;
}
return err;
}
/* Calculate the length of a packet described by PKT. */
u32
calc_packet_length( PACKET *pkt )
@ -637,8 +678,14 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
{
if ( (pk->pubkey_algo == PUBKEY_ALGO_ECDSA && (i == 0))
|| (pk->pubkey_algo == PUBKEY_ALGO_EDDSA && (i == 0))
|| (pk->pubkey_algo == PUBKEY_ALGO_ECDH && (i == 0 || i == 2)))
err = gpg_mpi_write_nohdr (a, pk->pkey[i]);
|| (pk->pubkey_algo == PUBKEY_ALGO_ECDH && (i == 0 || i == 2))
|| (pk->pubkey_algo == PUBKEY_ALGO_KYBER && (i == 0)))
err = gpg_mpi_write_opaque_nohdr (a, pk->pkey[i]);
else if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && i == 2)
{
/* Write a four-octet count prefixed Kyber public key. */
err = gpg_mpi_write_opaque_32 (a, pk->pkey[2], NULL);
}
else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH)
@ -777,9 +824,15 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
for (j=i; j < nskey; j++ )
{
if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH)
if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && j == 4)
{
if ((err=gpg_mpi_write_opaque_32 (NULL,pk->pkey[j], &n)))
goto leave;
}
else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH
|| pk->pubkey_algo == PUBKEY_ALGO_KYBER)
{
if ((err = sos_write (NULL, pk->pkey[j], &n)))
goto leave;
@ -796,16 +849,26 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
}
for ( ; i < nskey; i++ )
if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH)
{
if ((err = sos_write (a, pk->pkey[i], NULL)))
goto leave;
}
else
if ((err = gpg_mpi_write (a, pk->pkey[i], NULL)))
goto leave;
{
if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && i == 4)
{
err = gpg_mpi_write_opaque_32 (a, pk->pkey[i], NULL);
if (err)
goto leave;
}
else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH)
{
if ((err = sos_write (a, pk->pkey[i], NULL)))
goto leave;
}
else
{
if ((err = gpg_mpi_write (a, pk->pkey[i], NULL)))
goto leave;
}
}
write_16 (a, ski->csum );
}
@ -919,9 +982,19 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
for (i=0; i < n && !rc ; i++ )
{
if (enc->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1)
rc = gpg_mpi_write_nohdr (a, enc->data[i]);
else if (enc->pubkey_algo == PUBKEY_ALGO_ECDH)
/* For Kyber we need to insert the algo before the final data
* element because it is not stored in the data array. */
if (enc->pubkey_algo == PUBKEY_ALGO_KYBER && i == 2)
iobuf_put (a, enc->seskey_algo);
if (i == 1 && enc->pubkey_algo == PUBKEY_ALGO_ECDH)
rc = gpg_mpi_write_opaque_nohdr (a, enc->data[i]);
else if (i == 1 && enc->pubkey_algo == PUBKEY_ALGO_KYBER)
rc = gpg_mpi_write_opaque_32 (a, enc->data[i], NULL);
else if (i == 2 && enc->pubkey_algo == PUBKEY_ALGO_KYBER)
rc = gpg_mpi_write_opaque_nohdr (a, enc->data[i]);
else if (enc->pubkey_algo == PUBKEY_ALGO_ECDH
|| enc->pubkey_algo == PUBKEY_ALGO_KYBER)
rc = sos_write (a, enc->data[i], NULL);
else
rc = gpg_mpi_write (a, enc->data[i], NULL);
@ -1746,6 +1819,72 @@ sig_to_notation(PKT_signature *sig)
return list;
}
/* Return a list of notation data matching NAME. The caller needs to
* to free the list using free_notation. Other than sig_to_notation
* this function does not return the notation in human readable format
* but always returns the raw data. The human readable flag is set
* anyway set but .value is always NULL. */
struct notation *
search_sig_notations (PKT_signature *sig, const char *name)
{
const byte *p;
size_t len;
int seq = 0;
int crit;
notation_t list = NULL;
while((p=enum_sig_subpkt (sig, 1, SIGSUBPKT_NOTATION, &len, &seq, &crit)))
{
int n1,n2;
struct notation *n=NULL;
if (len < 8)
{
log_info (_("WARNING: invalid notation data found\n"));
continue;
}
/* name length. */
n1=(p[4]<<8)|p[5];
/* value length. */
n2=(p[6]<<8)|p[7];
if (8 + n1 + n2 != len)
{
log_info (_("WARNING: invalid notation data found\n"));
continue;
}
if (!name)
; /* Return everything. */
else if (n1 != strlen (name) || memcmp (p+8, name, n1))
continue; /* Not the requested name. */
n = xmalloc_clear (sizeof *n);
n->name = xmalloc (n1+1);
memcpy (n->name,p + 8, n1);
n->name[n1]='\0';
/* In any case append a Nul. */
n->bdat = xmalloc (n2+1);
memcpy (n->bdat, p + 8 + n1, n2);
n->bdat[n2] = '\0';
n->blen = n2;
n->flags.human = !!(p[0] & 0x80);
n->flags.critical = crit;
n->next = list;
list = n;
}
return list;
}
/* Release the resources associated with the *list* of notations. To
release a single notation, make sure that notation->next is
NULL. */

View File

@ -251,7 +251,8 @@ start_agent (ctrl_t ctrl, int flag_for_card)
opt.agent_program,
opt.lc_ctype, opt.lc_messages,
opt.session_env,
opt.autostart, opt.verbose, DBG_IPC,
opt.autostart?ASSHELP_FLAG_AUTOSTART:0,
opt.verbose, DBG_IPC,
NULL, NULL);
if (!opt.autostart && gpg_err_code (rc) == GPG_ERR_NO_AGENT)
{
@ -1079,6 +1080,12 @@ agent_keytotpm (ctrl_t ctrl, const char *hexgrip)
snprintf(line, DIM(line), "KEYTOTPM %s\n", hexgrip);
if (strchr (hexgrip, ','))
{
log_error ("storing a part of a dual key is not yet supported\n");
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
rc = start_agent (ctrl, 0);
if (rc)
return rc;
@ -1108,6 +1115,13 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
memset (&parm, 0, sizeof parm);
if (strchr (hexgrip, ','))
{
log_error ("storing a part of a dual key is not yet supported\n");
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
snprintf (line, DIM(line), "KEYTOCARD %s%s %s OPENPGP.%d %s%s%s",
force?"--force ": "", hexgrip, serialno, keyno, timestamp,
ecdh_param_str? " ":"", ecdh_param_str? ecdh_param_str:"");
@ -2239,9 +2253,9 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
{
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
char *hexgrip;
char *hexgrip, *p;
struct keyinfo_data_parm_s keyinfo;
int result, result2;
memset (&keyinfo, 0, sizeof keyinfo);
@ -2252,28 +2266,64 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
err = hexkeygrip_from_pk (pk, &hexgrip);
if (err)
return 0;
if ((p=strchr (hexgrip, ',')))
*p++ = 0;
snprintf (line, sizeof line, "KEYINFO %s", hexgrip);
xfree (hexgrip);
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
keyinfo_status_cb, &keyinfo);
xfree (keyinfo.serialno);
if (err)
return 0;
result = 0;
else if (keyinfo.card_available)
result = 4;
else if (keyinfo.passphrase_cached)
result = 3;
else if (keyinfo.is_smartcard)
result = 2;
else
result = 1;
if (keyinfo.card_available)
return 4;
if (!p)
{
xfree (hexgrip);
return result; /* Not a dual algo - we are ready. */
}
if (keyinfo.passphrase_cached)
return 3;
/* Now check the second keygrip. */
memset (&keyinfo, 0, sizeof keyinfo);
snprintf (line, sizeof line, "KEYINFO %s", p);
if (keyinfo.is_smartcard)
return 2;
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
keyinfo_status_cb, &keyinfo);
xfree (keyinfo.serialno);
if (err)
result2 = 0;
else if (keyinfo.card_available)
result2 = 4;
else if (keyinfo.passphrase_cached)
result2 = 3;
else if (keyinfo.is_smartcard)
result2 = 2;
else
result2 = 1;
return 1;
xfree (hexgrip);
if (result == result2)
return result; /* Both keys have the same status. */
else if (!result && result2)
return 0; /* Only first key available - return no key. */
else if (result && !result2)
return 0; /* Only second key not availabale - return no key. */
else if (result == 4 || result == 2)
return result; /* First key on card - don't care where the second is. */
else
return result;
}
/* Ask the agent whether a secret key is available for any of the
keys (primary or sub) in KEYBLOCK. Returns 0 if available. */
gpg_error_t
@ -2285,6 +2335,8 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
kbnode_t kbctx, node;
int nkeys; /* (always zero in secret_keygrips mode) */
unsigned char grip[KEYGRIP_LEN];
unsigned char grip2[KEYGRIP_LEN];
int grip2_valid;
const unsigned char *s;
unsigned int n;
@ -2319,8 +2371,9 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
}
if (err)
{
log_info ("problem with fast path key listing: %s - ignored\n",
gpg_strerror (err));
if (opt.quiet)
log_info ("problem with fast path key listing: %s - ignored\n",
gpg_strerror (err));
err = 0;
}
/* We want to do this only once. */
@ -2339,22 +2392,30 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
if (ctrl && ctrl->secret_keygrips)
{
/* We got an array with all secret keygrips. Check this. */
err = keygrip_from_pk (node->pkt->pkt.public_key, grip);
err = keygrip_from_pk (node->pkt->pkt.public_key, grip, 0);
if (err)
return err;
err = keygrip_from_pk (node->pkt->pkt.public_key, grip2, 1);
if (err && gpg_err_code (err) != GPG_ERR_FALSE)
return err;
grip2_valid = !err;
for (s=ctrl->secret_keygrips, n = 0;
n < ctrl->secret_keygrips_len;
s += 20, n += 20)
{
if (!memcmp (s, grip, 20))
return 0;
if (grip2_valid && !memcmp (s, grip2, 20))
return 0;
}
err = gpg_error (GPG_ERR_NO_SECKEY);
/* Keep on looping over the keyblock. Never bump nkeys. */
}
else
{
if (nkeys && ((p - line) + 41) > (ASSUAN_LINELENGTH - 2))
if (nkeys
&& ((p - line) + 4*KEYGRIP_LEN+1+1) > (ASSUAN_LINELENGTH - 2))
{
err = assuan_transact (agent_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
@ -2364,13 +2425,24 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
nkeys = 0;
}
err = keygrip_from_pk (node->pkt->pkt.public_key, grip);
err = keygrip_from_pk (node->pkt->pkt.public_key, grip, 0);
if (err)
return err;
*p++ = ' ';
bin2hex (grip, 20, p);
p += 40;
nkeys++;
err = keygrip_from_pk (node->pkt->pkt.public_key, grip2, 1);
if (err && gpg_err_code (err) != GPG_ERR_FALSE)
return err;
if (!err) /* Add the second keygrip from dual algos. */
{
*p++ = ' ';
bin2hex (grip2, 20, p);
p += 40;
nkeys++;
}
}
}
@ -2397,6 +2469,7 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
struct keyinfo_data_parm_s keyinfo;
const char *s;
memset (&keyinfo, 0,sizeof keyinfo);
@ -2406,10 +2479,20 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
if (err)
return err;
if (!hexkeygrip || strlen (hexkeygrip) != 40)
/* FIXME: Support dual keys. Maybe under the assumption that the
* first key might be on a card. */
if (!hexkeygrip)
return gpg_error (GPG_ERR_INV_VALUE);
s = strchr (hexkeygrip, ',');
if (!s)
s = hexkeygrip + strlen (hexkeygrip);
if (s - hexkeygrip != 40)
return gpg_error (GPG_ERR_INV_VALUE);
snprintf (line, DIM(line), "KEYINFO %s", hexkeygrip);
/* Note that for a dual algo we only get info for the first key.
* FIXME: We need to see how we can show the status of the second
* key in a key listing. */
snprintf (line, DIM(line), "KEYINFO %.40s", hexkeygrip);
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
keyinfo_status_cb, &keyinfo);
@ -2795,6 +2878,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
membuf_t data;
size_t n, len;
char *p, *buf, *endp;
const char *keygrip2 = NULL;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
@ -2803,13 +2887,26 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
dfltparm.keyinfo.mainkeyid = mainkeyid;
dfltparm.keyinfo.pubkey_algo = pubkey_algo;
if (!keygrip || strlen(keygrip) != 40
|| !s_ciphertext || !r_buf || !r_buflen || !r_padding)
if (!keygrip || !s_ciphertext || !r_buf || !r_buflen || !r_padding)
return gpg_error (GPG_ERR_INV_VALUE);
*r_buf = NULL;
*r_padding = -1;
/* Parse the keygrip in case of a dual algo. */
keygrip2 = strchr (keygrip, ',');
if (!keygrip2)
keygrip2 = keygrip + strlen (keygrip);
if (keygrip2 - keygrip != 40)
return gpg_error (GPG_ERR_INV_VALUE);
if (*keygrip2)
{
keygrip2++;
if (strlen (keygrip2) != 40)
return gpg_error (GPG_ERR_INV_VALUE);
}
err = start_agent (ctrl, 0);
if (err)
return err;
@ -2820,11 +2917,19 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
if (err)
return err;
snprintf (line, sizeof line, "SETKEY %s", keygrip);
snprintf (line, sizeof line, "SETKEY %.40s", keygrip);
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
if (*keygrip2)
{
snprintf (line, sizeof line, "SETKEY --another %.40s", keygrip2);
err = assuan_transact (agent_ctx, line, NULL, NULL,NULL,NULL,NULL,NULL);
if (err)
return err;
}
if (desc)
{
snprintf (line, DIM(line), "SETKEYDESC %s", desc);
@ -2843,7 +2948,8 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen);
if (err)
return err;
err = assuan_transact (agent_ctx, "PKDECRYPT",
err = assuan_transact (agent_ctx,
*keygrip2? "PKDECRYPT --kem=PQC-PGP":"PKDECRYPT",
put_membuf_cb, &data,
inq_ciphertext_cb, &parm,
padding_info_cb, r_padding);
@ -3173,6 +3279,7 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
return err;
}
/* FIXME: Shall we add support to DELETE_KEY for dual keys? */
snprintf (line, DIM(line), "DELETE_KEY%s %s",
force? " --force":"", hexkeygrip);
err = assuan_transact (agent_ctx, line, NULL, NULL,

View File

@ -166,7 +166,8 @@ create_context (ctrl_t ctrl, assuan_context_t *r_ctx)
err = start_new_dirmngr (&ctx,
GPG_ERR_SOURCE_DEFAULT,
opt.dirmngr_program,
opt.autostart, opt.verbose, DBG_IPC,
opt.autostart?ASSHELP_FLAG_AUTOSTART:0,
opt.verbose, DBG_IPC,
NULL /*gpg_status2*/, ctrl);
if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_DIRMNGR)
{

View File

@ -94,8 +94,6 @@ gpg_keyboxd_deinit_session_data (ctrl_t ctrl)
log_error ("oops: trying to cleanup an active keyboxd context\n");
else
{
kbx_client_data_release (kbl->kcd);
kbl->kcd = NULL;
if (kbl->ctx && in_transaction)
{
/* This is our hack to commit the changes done during a
@ -112,6 +110,15 @@ gpg_keyboxd_deinit_session_data (ctrl_t ctrl)
}
assuan_release (kbl->ctx);
kbl->ctx = NULL;
/*
* Since there may be pipe output FD sent to the server (so
* that it can receive data through the pipe), we should
* release the assuan connection before releasing KBL->KCD.
* This way, the data receiving thread can finish cleanly,
* and we can join the thread.
*/
kbx_client_data_release (kbl->kcd);
kbl->kcd = NULL;
}
xfree (kbl);
}
@ -143,7 +150,8 @@ create_new_context (ctrl_t ctrl, assuan_context_t *r_ctx)
err = start_new_keyboxd (&ctx,
GPG_ERR_SOURCE_DEFAULT,
opt.keyboxd_program,
opt.autostart, opt.verbose, DBG_IPC,
opt.autostart?ASSHELP_FLAG_AUTOSTART:0,
opt.verbose, DBG_IPC,
NULL, ctrl);
if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_KEYBOXD)
{
@ -223,7 +231,7 @@ open_context (ctrl_t ctrl, keyboxd_local_t *r_kbl)
return err;
}
err = kbx_client_data_new (&kbl->kcd, kbl->ctx, 1);
err = kbx_client_data_new (&kbl->kcd, kbl->ctx, 0);
if (err)
{
assuan_release (kbl->ctx);

View File

@ -28,9 +28,7 @@
# include <readline/readline.h>
#endif /*HAVE_LIBREADLINE*/
#if GNUPG_MAJOR_VERSION != 1
# include "gpg.h"
#endif /*GNUPG_MAJOR_VERSION != 1*/
#include "../common/util.h"
#include "../common/i18n.h"
#include "../common/ttyio.h"
@ -39,11 +37,7 @@
#include "main.h"
#include "keyserver-internal.h"
#if GNUPG_MAJOR_VERSION == 1
# include "cardglue.h"
#else /*GNUPG_MAJOR_VERSION!=1*/
# include "call-agent.h"
#endif /*GNUPG_MAJOR_VERSION!=1*/
#include "call-agent.h"
#define CONTROL_D ('D' - 'A' + 1)
@ -949,14 +943,6 @@ get_data_from_file (const char *fname, char **r_buffer)
*r_buffer = NULL;
fp = es_fopen (fname, "rb");
#if GNUPG_MAJOR_VERSION == 1
if (fp && is_secured_file (fileno (fp)))
{
fclose (fp);
fp = NULL;
errno = EPERM;
}
#endif
if (!fp)
{
tty_printf (_("can't open '%s': %s\n"), fname, strerror (errno));
@ -992,14 +978,6 @@ put_data_to_file (const char *fname, const void *buffer, size_t length)
estream_t fp;
fp = es_fopen (fname, "wb");
#if GNUPG_MAJOR_VERSION == 1
if (fp && is_secured_file (fileno (fp)))
{
fclose (fp);
fp = NULL;
errno = EPERM;
}
#endif
if (!fp)
{
tty_printf (_("can't create '%s': %s\n"), fname, strerror (errno));

View File

@ -53,7 +53,11 @@ init_compress( compress_filter_context_t *zfx, bz_stream *bzs )
}
if((rc=BZ2_bzCompressInit(bzs,level,0,0))!=BZ_OK)
log_fatal("bz2lib problem: %d\n",rc);
{
log_error ("bz2lib problem: %d\n",rc);
write_status_error ("bzip2.init", gpg_error (GPG_ERR_INTERNAL));
g10_exit (2);
}
zfx->outbufsize = 8192;
zfx->outbuf = xmalloc( zfx->outbufsize );
@ -80,7 +84,11 @@ do_compress(compress_filter_context_t *zfx, bz_stream *bzs, int flush, IOBUF a)
if( zrc == BZ_STREAM_END && flush == BZ_FINISH )
;
else if( zrc != BZ_RUN_OK && zrc != BZ_FINISH_OK )
log_fatal("bz2lib deflate problem: rc=%d\n", zrc );
{
log_error ("bz2lib deflate problem: rc=%d\n", zrc );
write_status_error ("bzip2.deflate", gpg_error (GPG_ERR_INTERNAL));
g10_exit (2);
}
n = zfx->outbufsize - bzs->avail_out;
if( DBG_FILTER )
@ -91,7 +99,7 @@ do_compress(compress_filter_context_t *zfx, bz_stream *bzs, int flush, IOBUF a)
if( (rc=iobuf_write( a, zfx->outbuf, n )) )
{
log_debug("bzCompress: iobuf_write failed\n");
log_error ("bzCompress: iobuf_write failed\n");
return rc;
}
}
@ -106,7 +114,11 @@ init_uncompress( compress_filter_context_t *zfx, bz_stream *bzs )
int rc;
if((rc=BZ2_bzDecompressInit(bzs,0,opt.bz2_decompress_lowmem))!=BZ_OK)
log_fatal("bz2lib problem: %d\n",rc);
{
log_error ("bz2lib problem: %d\n",rc);
write_status_error ("bzip2.init.un", gpg_error (GPG_ERR_INTERNAL));
g10_exit (2);
}
zfx->inbufsize = 2048;
zfx->inbuf = xmalloc( zfx->inbufsize );
@ -159,7 +171,11 @@ do_uncompress( compress_filter_context_t *zfx, bz_stream *bzs,
if( zrc == BZ_STREAM_END )
rc = -1; /* eof */
else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR )
log_fatal("bz2lib inflate problem: rc=%d\n", zrc );
{
log_error ("bz2lib inflate problem: rc=%d\n", zrc );
write_status_error ("bzip2.inflate", gpg_error (GPG_ERR_BAD_DATA));
g10_exit (2);
}
else if (zrc == BZ_OK && eofseen
&& !bzs->avail_in && bzs->avail_out > 0)
{

View File

@ -73,10 +73,12 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs )
-13, 8, Z_DEFAULT_STRATEGY)
: deflateInit( zs, level )
) != Z_OK ) {
log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
log_error ("zlib problem: %s\n", zs->msg? zs->msg :
rc == Z_MEM_ERROR ? "out of core" :
rc == Z_VERSION_ERROR ? "invalid lib version" :
"unknown error" );
write_status_error ("zlib.init", gpg_error (GPG_ERR_INTERNAL));
g10_exit (2);
}
zfx->outbufsize = 8192;
@ -104,9 +106,11 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
;
else if( zrc != Z_OK ) {
if( zs->msg )
log_fatal("zlib deflate problem: %s\n", zs->msg );
log_error ("zlib deflate problem: %s\n", zs->msg );
else
log_fatal("zlib deflate problem: rc=%d\n", zrc );
log_error ("zlib deflate problem: rc=%d\n", zrc );
write_status_error ("zlib.deflate", gpg_error (GPG_ERR_INTERNAL));
g10_exit (2);
}
n = zfx->outbufsize - zs->avail_out;
if( DBG_FILTER )
@ -116,7 +120,7 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
(unsigned)n, zrc );
if( (rc=iobuf_write( a, zfx->outbuf, n )) ) {
log_debug("deflate: iobuf_write failed\n");
log_error ("deflate: iobuf_write failed\n");
return rc;
}
} while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
@ -140,10 +144,12 @@ init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
*/
if( (rc = zfx->algo == 1? inflateInit2( zs, -15)
: inflateInit( zs )) != Z_OK ) {
log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
rc == Z_MEM_ERROR ? "out of core" :
rc == Z_VERSION_ERROR ? "invalid lib version" :
"unknown error" );
log_error ("zlib problem: %s\n", zs->msg? zs->msg :
rc == Z_MEM_ERROR ? "out of core" :
rc == Z_VERSION_ERROR ? "invalid lib version" :
"unknown error" );
write_status_error ("zlib.init.un", gpg_error (GPG_ERR_INTERNAL));
g10_exit (2);
}
zfx->inbufsize = 2048;
@ -198,9 +204,11 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
rc = -1; /* eof */
else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
if( zs->msg )
log_fatal("zlib inflate problem: %s\n", zs->msg );
log_error ("zlib inflate problem: %s\n", zs->msg );
else
log_fatal("zlib inflate problem: rc=%d\n", zrc );
log_error ("zlib inflate problem: rc=%d\n", zrc );
write_status_error ("zlib.inflate", gpg_error (GPG_ERR_BAD_DATA));
g10_exit (2);
}
} while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR
&& !leave);

View File

@ -63,7 +63,7 @@ dearmor_file( const char *fname )
push_armor_filter ( afx, inp );
if( (rc = open_outfile (-1, fname, 0, 0, &out)) )
if( (rc = open_outfile (GNUPG_INVALID_FD, fname, 0, 0, &out)) )
goto leave;
iobuf_copy (out, inp);
@ -107,7 +107,7 @@ enarmor_file( const char *fname )
}
if( (rc = open_outfile (-1, fname, 1, 0, &out )) )
if( (rc = open_outfile (GNUPG_INVALID_FD, fname, 1, 0, &out )) )
goto leave;
afx->what = 4;

View File

@ -205,6 +205,7 @@ aead_checktag (decode_filter_ctx_t dfx, int final, const void *tagbuf)
{
log_error ("gcry_cipher_checktag%s failed: %s\n",
final? " (final)":"", gpg_strerror (err));
write_status_error ("aead_checktag", err);
return err;
}
if (DBG_FILTER)

View File

@ -100,7 +100,8 @@ decrypt_message (ctrl_t ctrl, const char *filename)
/* Same as decrypt_message but takes a file descriptor for input and
output. */
gpg_error_t
decrypt_message_fd (ctrl_t ctrl, int input_fd, int output_fd)
decrypt_message_fd (ctrl_t ctrl, gnupg_fd_t input_fd,
gnupg_fd_t output_fd)
{
#ifdef HAVE_W32_SYSTEM
/* No server mode yet. */
@ -138,13 +139,25 @@ decrypt_message_fd (ctrl_t ctrl, int input_fd, int output_fd)
return err;
}
opt.outfp = es_fdopen_nc (output_fd, "wb");
if (is_secured_file (output_fd))
{
char xname[64];
err = gpg_error (GPG_ERR_EPERM);
snprintf (xname, sizeof xname, "[fd %d]", FD_DBG (output_fd));
log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
iobuf_close (fp);
release_progress_context (pfx);
return err;
}
opt.outfp = open_stream_nc (output_fd, "w");
if (!opt.outfp)
{
char xname[64];
err = gpg_error_from_syserror ();
snprintf (xname, sizeof xname, "[fd %d]", output_fd);
snprintf (xname, sizeof xname, "[fd %d]", FD_DBG (output_fd));
log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
iobuf_close (fp);
release_progress_context (pfx);

View File

@ -156,11 +156,11 @@ build_kdf_params (unsigned char kdf_params[256], size_t *r_size,
return gpg_error_from_syserror ();
/* variable-length field 1, curve name OID */
err = gpg_mpi_write_nohdr (obuf, pkey[0]);
err = gpg_mpi_write_opaque_nohdr (obuf, pkey[0]);
/* fixed-length field 2 */
iobuf_put (obuf, PUBKEY_ALGO_ECDH);
/* variable-length field 3, KDF params */
err = (err ? err : gpg_mpi_write_nohdr (obuf, pkey[2]));
err = (err ? err : gpg_mpi_write_opaque_nohdr (obuf, pkey[2]));
/* fixed-length field 4 */
iobuf_write (obuf, "Anonymous Sender ", 20);
/* fixed-length field 5, recipient fp (or first 20 octets of fp) */
@ -524,8 +524,7 @@ pk_ecdh_decrypt (gcry_mpi_t *r_result, const byte sk_fp[MAX_FINGERPRINT_LEN],
size_t nbytes;
byte *data_buf;
int data_buf_size;
byte *in;
const void *p;
const unsigned char *p;
unsigned int nbits;
*r_result = NULL;
@ -538,7 +537,7 @@ pk_ecdh_decrypt (gcry_mpi_t *r_result, const byte sk_fp[MAX_FINGERPRINT_LEN],
nbytes = (nbits+7)/8;
data_buf_size = nbytes;
if ((data_buf_size & 7) != 1)
if ((data_buf_size & 7) != 1 || data_buf_size <= 1 + 8)
{
log_error ("can't use a shared secret of %d bytes for ecdh\n",
data_buf_size);
@ -546,7 +545,10 @@ pk_ecdh_decrypt (gcry_mpi_t *r_result, const byte sk_fp[MAX_FINGERPRINT_LEN],
return gpg_error (GPG_ERR_BAD_DATA);
}
data_buf = xtrymalloc_secure( 1 + 2*data_buf_size + 8);
/* The first octet is for length. It's longer than the result
because of one additional block of AESWRAP. */
data_buf_size -= 1 + 8;
data_buf = xtrymalloc_secure (data_buf_size);
if (!data_buf)
{
err = gpg_error_from_syserror ();
@ -560,22 +562,18 @@ pk_ecdh_decrypt (gcry_mpi_t *r_result, const byte sk_fp[MAX_FINGERPRINT_LEN],
gcry_cipher_close (hd);
return gpg_error (GPG_ERR_BAD_MPI);
}
memcpy (data_buf, p, nbytes);
if (data_buf[0] != nbytes-1)
if (p[0] != nbytes-1)
{
log_error ("ecdh inconsistent size\n");
xfree (data_buf);
gcry_cipher_close (hd);
return gpg_error (GPG_ERR_BAD_MPI);
}
in = data_buf+data_buf_size;
data_buf_size = data_buf[0];
if (DBG_CRYPTO)
log_printhex (data_buf+1, data_buf_size, "ecdh decrypting :");
log_printhex (p+1, nbytes-1, "ecdh decrypting :");
err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
data_buf_size);
err = gcry_cipher_decrypt (hd, data_buf, data_buf_size, p+1, nbytes-1);
gcry_cipher_close (hd);
if (err)
{
@ -585,10 +583,8 @@ pk_ecdh_decrypt (gcry_mpi_t *r_result, const byte sk_fp[MAX_FINGERPRINT_LEN],
return err;
}
data_buf_size -= 8;
if (DBG_CRYPTO)
log_printhex (in, data_buf_size, "ecdh decrypted to :");
log_printhex (data_buf, data_buf_size, "ecdh decrypted to :");
/* Padding is removed later. */
/* if (in[data_buf_size-1] > 8 ) */
@ -598,7 +594,8 @@ pk_ecdh_decrypt (gcry_mpi_t *r_result, const byte sk_fp[MAX_FINGERPRINT_LEN],
/* return gpg_error (GPG_ERR_BAD_KEY); */
/* } */
err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, data_buf,
data_buf_size, NULL);
xfree (data_buf);
if (err)
{

View File

@ -507,7 +507,8 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
/**/ : "CFB");
}
if ( rc || (rc = open_outfile (-1, filename, opt.armor? 1:0, 0, &out )))
if (rc || (rc = open_outfile (GNUPG_INVALID_FD, filename, opt.armor? 1:0,
0, &out )))
{
iobuf_cancel (inp);
xfree (cfx.dek);
@ -757,15 +758,15 @@ write_symkey_enc (STRING2KEY *symkey_s2k, aead_algo_t aead_algo,
* Encrypt the file with the given userids (or ask if none is
* supplied). Either FILENAME or FILEFD must be given, but not both.
* The caller may provide a checked list of public keys in
* PROVIDED_PKS; if not the function builds a list of keys on its own.
* PROVIDED_KEYS; if not the function builds a list of keys on its own.
*
* Note that FILEFD is currently only used by cmd_encrypt in the
* not yet finished server.c.
*/
int
encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
encrypt_crypt (ctrl_t ctrl, gnupg_fd_t filefd, const char *filename,
strlist_t remusr, int use_symkey, pk_list_t provided_keys,
int outputfd)
gnupg_fd_t outputfd)
{
iobuf_t inp = NULL;
iobuf_t out = NULL;
@ -783,7 +784,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
PK_LIST pk_list;
int do_compress;
if (filefd != -1 && filename)
if (filefd != GNUPG_INVALID_FD && filename)
return gpg_error (GPG_ERR_INV_ARG); /* Both given. */
do_compress = !!opt.compress_algo;
@ -814,7 +815,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
/* Prepare iobufs. */
#ifdef HAVE_W32_SYSTEM
if (filefd == -1)
if (filefd == GNUPG_INVALID_FD)
inp = iobuf_open (filename);
else
{
@ -822,7 +823,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
gpg_err_set_errno (ENOSYS);
}
#else
if (filefd == -1)
if (filefd == GNUPG_INVALID_FD)
inp = iobuf_open (filename);
else
inp = iobuf_fdopen_nc (filefd, "rb");
@ -840,8 +841,8 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
char xname[64];
rc = gpg_error_from_syserror ();
if (filefd != -1)
snprintf (xname, sizeof xname, "[fd %d]", filefd);
if (filefd != GNUPG_INVALID_FD)
snprintf (xname, sizeof xname, "[fd %d]", FD_DBG (filefd));
else if (!filename)
strcpy (xname, "[stdin]");
else
@ -1121,6 +1122,7 @@ write_pubkey_enc (ctrl_t ctrl,
enc->pubkey_algo = pk->pubkey_algo;
keyid_from_pk( pk, enc->keyid );
enc->throw_keyid = throw_keyid;
enc->seskey_algo = dek->algo; /* (Used only by PUBKEY_ALGO_KYBER.) */
/* Okay, what's going on: We have the session key somewhere in
* the structure DEK and want to encode this session key in an
@ -1136,7 +1138,7 @@ write_pubkey_enc (ctrl_t ctrl,
* build_packet(). */
frame = encode_session_key (pk->pubkey_algo, dek,
pubkey_nbits (pk->pubkey_algo, pk->pkey));
rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, pk, pk->pkey);
rc = pk_encrypt (pk, frame, dek->algo, enc->data);
gcry_mpi_release (frame);
if (rc)
log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
@ -1224,7 +1226,8 @@ encrypt_crypt_files (ctrl_t ctrl, int nfiles, char **files, strlist_t remusr)
}
line[strlen(line)-1] = '\0';
print_file_status(STATUS_FILE_START, line, 2);
rc = encrypt_crypt (ctrl, -1, line, remusr, 0, NULL, -1);
rc = encrypt_crypt (ctrl, GNUPG_INVALID_FD, line, remusr,
0, NULL, GNUPG_INVALID_FD);
if (rc)
log_error ("encryption of '%s' failed: %s\n",
print_fname_stdin(line), gpg_strerror (rc) );
@ -1236,7 +1239,8 @@ encrypt_crypt_files (ctrl_t ctrl, int nfiles, char **files, strlist_t remusr)
while (nfiles--)
{
print_file_status(STATUS_FILE_START, *files, 2);
if ( (rc = encrypt_crypt (ctrl, -1, *files, remusr, 0, NULL, -1)) )
if ((rc = encrypt_crypt (ctrl, GNUPG_INVALID_FD, *files, remusr,
0, NULL, GNUPG_INVALID_FD)))
log_error("encryption of '%s' failed: %s\n",
print_fname_stdin(*files), gpg_strerror (rc) );
write_status( STATUS_FILE_DONE );

View File

@ -129,6 +129,8 @@ parse_export_options(char *str,unsigned int *options,int noisy)
N_("export revocation keys marked as \"sensitive\"")},
{"export-clean",EXPORT_CLEAN,NULL,
N_("remove unusable parts from key during export")},
{"export-realclean",EXPORT_MINIMAL|EXPORT_REALCLEAN|EXPORT_CLEAN,NULL,
NULL},
{"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
N_("remove as much as possible from key during export")},
@ -166,7 +168,7 @@ parse_export_options(char *str,unsigned int *options,int noisy)
{
*options |= (EXPORT_LOCAL_SIGS | EXPORT_ATTRIBUTES
| EXPORT_SENSITIVE_REVKEYS);
*options &= ~(EXPORT_CLEAN | EXPORT_MINIMAL
*options &= ~(EXPORT_CLEAN | EXPORT_MINIMAL | EXPORT_REALCLEAN
| EXPORT_DANE_FORMAT);
}
@ -426,7 +428,7 @@ do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options,
memset( &zfx, 0, sizeof zfx);
rc = open_outfile (-1, NULL, 0, !!secret, &out );
rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, !!secret, &out);
if (rc)
return rc;
@ -643,7 +645,7 @@ canon_pk_algo (enum gcry_pk_algos algo)
}
/* Take an s-expression wit the public and private key and change the
/* Take an s-expression with the public and private key and change the
* parameter array in PK to include the secret parameters. */
static gpg_error_t
secret_key_to_mode1003 (gcry_sexp_t s_key, PKT_public_key *pk)
@ -1959,6 +1961,11 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
err = 0;
continue;
}
if (strchr (hexgrip, ','))
{
log_error ("exporting a secret dual key is not yet supported\n");
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
xfree (serialno);
serialno = NULL;
@ -2366,8 +2373,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
if ((options & EXPORT_CLEAN))
{
merge_keys_and_selfsig (ctrl, keyblock);
clean_all_uids (ctrl, keyblock, opt.verbose,
(options&EXPORT_MINIMAL), NULL, NULL);
clean_all_uids (ctrl, keyblock, opt.verbose, options, NULL, NULL);
clean_all_subkeys (ctrl, keyblock, opt.verbose,
(options&EXPORT_MINIMAL)? KEY_CLEAN_ALL
/**/ : KEY_CLEAN_AUTHENCR,
@ -2706,18 +2712,18 @@ export_one_ssh_key (estream_t fp, PKT_public_key *pk)
blob = get_membuf (&mb, &bloblen);
if (blob)
{
struct b64state b64_state;
gpgrt_b64state_t b64_state;
es_fprintf (fp, "%s ", identifier);
err = b64enc_start_es (&b64_state, fp, "");
if (err)
b64_state = gpgrt_b64enc_start (fp, "");
if (!b64_state)
{
xfree (blob);
goto leave;
}
err = b64enc_write (&b64_state, blob, bloblen);
b64enc_finish (&b64_state);
err = gpgrt_b64enc_write (b64_state, blob, bloblen);
gpgrt_b64enc_finish (b64_state);
es_fprintf (fp, " openpgp:0x%08lX\n", (ulong)keyid_from_pk (pk, NULL));
xfree (blob);
@ -2961,7 +2967,7 @@ export_secret_ssh_key (ctrl_t ctrl, const char *userid)
int pkalgo;
int i;
gcry_mpi_t keyparam[10] = { NULL };
struct b64state b64_state;
gpgrt_b64state_t b64_state;
init_membuf_secure (&mb, 1024);
init_membuf_secure (&mb2, 1024);
@ -3139,11 +3145,11 @@ export_secret_ssh_key (ctrl_t ctrl, const char *userid)
goto leave;
}
err = b64enc_start_es (&b64_state, fp, "OPENSSH PRIVATE_KEY");
if (err)
b64_state = gpgrt_b64enc_start (fp, "OPENSSH PRIVATE_KEY");
if (!b64_state)
goto leave;
err = b64enc_write (&b64_state, blob, bloblen);
b64enc_finish (&b64_state);
err = gpgrt_b64enc_write (b64_state, blob, bloblen);
gpgrt_b64enc_finish (b64_state);
if (err)
goto leave;

View File

@ -29,6 +29,9 @@ typedef struct {
size_t maxbuf_size;
} md_filter_context_t;
typedef struct md_thd_filter_context *md_thd_filter_context_t;
void md_thd_filter_set_md (md_thd_filter_context_t mfx, gcry_md_hd_t md);
typedef struct {
int refcount; /* Initialized to 1. */
@ -165,6 +168,7 @@ typedef struct {
/*-- mdfilter.c --*/
int md_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len);
int md_thd_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len);
void free_md_filter_context( md_filter_context_t *mfx );
/*-- armor.c --*/

Some files were not shown because too many files have changed in this diff Show More