Question about the security of the GnuPG Agent with regard to cryptographic material scrubbing

Ángel angel at pgp.16bits.net
Wed Feb 27 00:14:34 CET 2019


On 2019-02-26 at 11:02 +0200, Ciprian Dorin Craciun wrote:
> Hello all!
> 
> Given the recent survey in password managers security [1], which
> concluded with their failure to properly sanitize / scrub the
> sensitive data (i.e. "master key") in "running locked state", I was
> wondering how does GnuPG Agent fare in this regard?
> 
> More specifically:
> * let's assume that one uses GnuPG Agent;  (only for PGP;)
> * the user enters the password for a particular private key;
> * (one assumes that the password was used to get the private key
> cryptographic material, and then scrubbed;)
> * then `--max-cache-ttl` seconds passes;
> * one assumes that the private key cryptographic material is now scrubbed;
> 
> Is this expectation correct?

I would say this is the right expectation.

However note that even with a perfect agent implementation, you might
find eg. that the kernel swapped to disk the page where the password was
read (before providing it to the program, which would hopefully be using
mlock(2) to avoid being swapped itself).



> Is there some external analysis about the security of the agent with
> regard to the scrubbing of both passwords and cryptographic material?

Intrigued by this I did a quick glance at the relevant code:

The cache purging seems to be done at housekeeping() [1], which simply calls release_data over the entry to free.
In turn, release_data() [2] is just a xfree() call, which would be
converted to gcry_free(), which is a libgcrypt function that will call
_gcry_private_free() [3].

_gcry_private_free() checks[4] whether this allocation was from a secure
pool (ie. allocated with gcry_xmalloc_secure), in which case it will
call _gcry_secmem_free[5], which does attempt to wipe the memory by
overwriting it with 0xff, 0xaa, 0x55 and 0x00 [6] using the macro
wipememory2,[7] which may do so inline (using volatile to avoid compiler
optimization) or end up calling _gcry_fast_wipememory, which would end
up calling the normal memset() through a function pointer.[8]
(I would expect either an attempt to use memset_s if available, similar
to the  check for explicit_bzero, or a note that like SecureZeroMemory
it provides no benefit, instead of a plain memset, though)

Best regards

[1] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=agent/cache.c;h=799d595abdb007422090622a959aa03741139c54;hb=HEAD#l198
[2] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=agent/cache.c;h=799d595abdb007422090622a959aa03741139c54;hb=HEAD#l141
[3] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=blob;f=src/global.c;h=d82c680a5d2a2981129d0531ff43b337ffebb085;hb=refs/heads/master#l1019
[4] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=blob;f=src/stdmem.c;h=04ce64fba14b2fd5d58be5050b80d6a159dffed5;hb=refs/heads/master#l220
[5] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=blob;f=src/secmem.c;h=b36c44f6de188ff005ca10800a4ba9fdf5a352d2;hb=refs/heads/master#l787
[6] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=blob;f=src/secmem.c;h=b36c44f6de188ff005ca10800a4ba9fdf5a352d2;hb=refs/heads/master#l768
[7] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=blob;f=src/g10lib.h;h=694c2d83e2682103d83be03070c737a1bb6a3ae4;hb=refs/heads/master#l337
[8] https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=blob;f=src/misc.c;h=bb39e1c2fe1c94affe1f024a87621f79e77ba1aa;hb=refs/heads/master#l504





More information about the Gnupg-users mailing list