Special note - GNU Privacy Guard and Agents

The GNU Privacy Guard (GPG) supports the use of an agent to manage encrypted keys. Agents allow for protocol independent access to keys stored in users' GPG keyrings.

FIS strongly recommends using a separate keyring and configuration for GT.M applications. The GPG keyring and related configuration files reside in $GNUPGHOME. Using a separate $GNUPGHOME insulates the GT.M application from interference with any user desktop/workstation environment. Configuration options necessary to support GT.M could negatively impact other programs and vice versa.

Starting with GPG version 2, GPG required the use of the agent. However, in testing, FIS has found that GPG Classic versions 1.4.16 and up, may also require an agent. While the following information is valid as of GPG release 2.1.18, later versions may introduce some wrinkles in the agent operation. Users must familiarize themselves with GPG while setting up encryption.

While GPG comes with an agent program, gpg-agent, other parties often provide their own agent implementation, e.g. gnome-keyring-daemon. These third party agents often start up, as a convenience, during user login to provide password and key caching services. Agents typically define GPG_AGENT_INFO in the environment pointing to a socket file. Since third-party agents define GPG_AGENT_INFO in the environment, GT.M scripts must undefine it to avoid communicating with the third party agents. It is possible that these third-party agents create the GPG default socket file $GNUPGHOME/S.gpg-agent. Using a separate $GNUPGHOME insulates a GT.M application from third part agents.

When invoking GPG via GPGME, there is no convenient way to avoid invoking an agent that obtains the passphrase for the keyring from the user. When the reference implementation has placed an obfuscated password in the environment, the password should be derived from that obfuscated password, and the user should not be prompted for the password. By default the GPG agent calls /usr/bin/pinentry the pinentry program. FIS provides a custom pinentry function for GT.M's encryption reference implementation (packaged in pinentry-gtm.sh and pinentry.m).

[Caution] Spurious CRYPTKEYFETCHFAILED errors

A defect that affects GnuPG 2.0+ versions causes the gpg-agent to fail decrypting the GnuPG private key that secures the database encryption key. This decryption failure results in spurious CRYPTKEYFETCHFAILED errors during process startup or re-encryption. This defect appears more frequently with GnuPG releases starting at 2.1.15. At the time of this writing, Ubuntu 17.04 - 17.10, Debian 9 and Fedora 26 - 27 all have the affected GnuPG versions. However Fedora 26 - 27 are slated to receive fixed versions.

GPG versions 2.1.15 and up suffer from persistent CRYPTKEYFETCHFAILED errors. The only recommended course of action is to upgrade to GnuPG 2.2.4 and libgcrypt 1.8.2 which contain the fixes for the defects https://dev.gnupg.org/T3473 and https://dev.gnupg.org/T3530. The GPG fixes that address the CRYPTKEYFETCHFAILED errors require additional gpg-agent configuration options listed below. Please kill and restart any existing GPG agent processes for the agent to pick up the changes.

Using the reference implementation's custom pinentry program

pinentry-gtm.sh is a custom pinentry program that prevents prompting for keyring passphrase by Gnu Privacy Guard operations when the environment variable gtm_passwd is already defined. When there is a GETPIN request and the gtm_passwd environment variable is defined, pinentry-gtm.sh runs pinentry.m and returns the to the calling program. Custom pinentry programs like pinentry-gtm.sh are meaningful only when you set gtm_passwd to an obfuscated passphrase. When the environment variable gtm_passwd is not defined or a usable mumps or pinentry.m does not exists, pinentry-gtm.sh runs the default pinentry program and prompts for passphrase. Remember that pinentry.m can reveal the passphrase. Therefore, ensure that you restrict the access for the pinentry.m's object file to only those users who manage your keys. GT.M provides pinentry-gtm.sh as a convenience to those users who are bothered by prompting for keyring passphrases for Gnu Privacy Guard related operations. Neither pinentry-gtm.sh nor pinentry.m is used internally by any GT.M database operation.

[Note] Note

When you set gtm_passwd to "", GT.M obtains the passphrase using the default GTMCRYPT passphrase prompt. When gtm_passwd is set to "", you can neither use a pinentry program (custom or default) to obtain a passphrase nor customize the default GTMCRYPT passphrase prompt.

To use the custom pinentry program, you need to perform the following setup actions:

  1. At the OS level, ensure that the default pinentry program for servers is the "curses" pinentry executable and not the GUI version. Should the custom pinentry program fail, GPG invokes the default pinentry program. If the default pinentry program is for the GUI, a console user typically would not become aware of the password request.

    For Redhat systems use 'yum search pinentry' to search for the available pinentry programs for the "curses" version.

    For Debian and Ubuntu systems use 'apt search pinentry' to search for the available pinentry programs for the "curses" version.

  2. GT.M scripts must undefine GPG_AGENT_INFO

  3. GT.M scripts must define GPG_TTY or the (GPG 2.1 and up) pinentry program may not work. e.g.:

    export GPG_TTY=$tty
  4. Set up the encryption keys using the gen_keypair.sh script. This script creates a file gpg-agent.conf in the GnuPG directory (specified by the environment variable $GNUPGHOME) with the following line directing GPG to invoke the reference implementation's custom pinentry program.

    pinentry-program <path to $gtm_dist>/plugin/gtmcrypt/pinetry-gtm.sh

    When pinetry-gtm.sh finds the environment variable $gtm_passwd defined and an executable GT.M, it runs the pinentry.m program which provides GnuPG with the keyring password from the obfuscated password. Otherwise, it calls /usr/bin/pinentry.

  5. The custom pinentry program uses a GT.M external call. Each GT.M application that uses pinentry-gtm.sh must define the environment variable GTMXC_gpgagent to point to the location of gpgagent.tab. By default, the reference implementation places gpgagent.tab in the $gtm_dist/plugin/ directory. gpgagent.tab is an external call table that pinentry.m uses to unmask the obfusacated password stored in gtm_passwd.

  6. Direct the gpg-agent to use it's standard Unix domain socket file, $GNUPGHOME/S.agent, when listening for password requests. Enabling the standard socket simplifies the gpg-agent configuration. Enable the standard socket by adding the following configuration option to $GNUPGHOME/gpg-agent.conf.

    echo "use-standard-socket" >> $GNUPGHOME/gpg-agent.conf
  7. When using GPG 2.1.12 and up, enable loopback pinentry mode by adding the following configuration option to $GNUPGHOME/gpg-agent.conf. With this option in place, the agent can call back to GT.M directly for the passphrase if GPG directs it to do so.

    echo "allow-loopback-pinentry" >> $GNUPGHOME/gpg-agent.conf
  8. When using GPG 2.1.12 and up with GT.M versions prior to V6.3-001, you can bypass the agent by forcing GPG to use pinentry loopback mode, by adding the following configuration option to $GNUPGHOME/gpg.conf. This eliminates the custom pinentry progam configuration.

    echo "pinentry-mode=loopback" >> $GNUPGHOME/gpg.conf
  9. When using GPG 2.2.4 and up use the option to auto-increase secmem in gpg-agent (https://dev.gnupg.org/T3530)

    echo "auto-expand-secmem" >> $GNUPGHOME/gpg-agent.conf
  10. When using GPG 2.2.4 and up use the option to increase the configurable backlog for sockets (https://dev.gnupg.org/T3473)

    echo "listen-backlog 128" >> $GNUPGHOME/gpg-agent.conf

For more information on other available options for your gpg-agent.conf, refer to the manpages of gpg-agent (man gpg-agent).

[Caution] Warning

The GT.M pinentry function should not be used while changing the keyring passphrase, e.g., the passwd subcommand of the gpg --edit-key command. Depending upon the gpg version ("man gpg" to confirm) you can override the agent configuration. Otherwise, you will need to temporarily comment out the pinentry-program line in gpg-agent.conf by placing a "#" in front of the line, e.g.:

#pinentry-program <path to $gtm_dist>/plugin/gtmcrypt/pinetry-gtm.sh

The encryption plugins included with GT.M releases prior to V5.4-001 are not compatible with GPG agents.