pinentry: Front ends

 
 2 Front Ends
 ************
 
 There are several different flavors of PINENTRY.  Concretely, there are
 Gtk+2, Qt 4, Gnome 3, Emacs, curses and tty variants.  These different
 implementations provide higher levels of integration with a specific
 environment.  For instance, the Gnome 3 PINENTRY uses Gnome 3 widgets to
 display the prompts.  For Gnome 3 users, this higher level of
 integration provides a more consistent aesthetic.  However, this comes
 at a cost.  Because this PINENTRY uses so many components, there is a
 larger chance of a failure.  In particular, there is a larger chance
 that the passphrase is saved in memory and that memory is exposed to an
 attacker (consider the OpenSSL Heartbeat vulnerability).
 
    To understand how many components touch the passphrase, consider
 again the Gnome 3 implementation.  When a user presses a button on the
 keyboard, the key is passed from the kernel to the X server to the
 toolkit (Gtk+) and to the actual text entry widget.  Along the way, the
 key is saved in memory and processed.  In fact, the key presses are
 probably read using standard C library functions, which buffer the
 input.  None of this code is careful to make sure the contents of the
 memory are not leaked by keeping the data in unpagable memory and wiping
 it when the buffer is freed.  However, even if they did, there is still
 the problem that when a computer hibernates, the system writes unpagable
 memory to disk anyway.  Further, many installations are virtualized
 (e.g., running on Xen) and have little control over their actual
 environment.
 
    The curses variant uses a significant smaller software stack and the
 tty variant uses an even smaller one.  However, if they are run in an
 X terminal, then a similar number of components are handling the
 passphrase as in the Gnome 3 case!  Thus, to be most secure, you need to
 direct GPG Agent to use a fixed virtual console.  Since you need to
 remain logged in for GPG Agent to use that console, you should run there
 and have 'screen' or 'tmux' lock the tty.
 
    The Emacs pinentry implementation interacts with a running Emacs
 session and directs the Emacs instance to display the passphrase prompt.
 Since this doesn't work very well if there is no Emacs running, the
 generic PINENTRY backend checks if a PINENTRY-enabled Emacs should be
 used.  Specifically, it looks to see if the 'INSIDE_EMACS' variable is
 set and then attempts to establish a connection to the specified
 address.  If this is the case, then instead of, e.g., 'pinentry-gtk2'
 displaying a Gtk+2 pinentry, it interacts with the Emacs session.  This
 functionality can be explicitly disabled by passing
 '--disable-inside-emacs' to 'configure' when building PINENTRY.
 
    Having Emacs get the passphrase is convenient, however, it is a
 significant security risk.  Emacs is a huge program, which doesn't
 provide any process isolation to speak of.  As such, having it handle
 the passphrase adds a huge chunk of code to the user's trusted computing
 base.  Because of this concern, Emacs doesn't enable this by default,
 unless the 'allow-emacs-pinentry' option is explicitly set in his or her
 '.gnupg/gpg-agent.conf' file.
 
    Similar to the inside-emacs check, the PINENTRY frontends check
 whether the 'DISPLAY' variable is set and a working X server is
 available.  If this is not the case, then they fallback to the curses
 front end.  This can also be disabled by passing
 '--disable-fallback-curses' to 'configure' at build time.