GPG: WinPT + KeePass = KeePT
KeePT is my new plugin for KeePass which allows to use WinPT from KeePass. There is no need to start both KeePass and WinPT at the same time. KeePT allows to access all functions from WinPT from KeePT's tray menu. Furthermore, the plugin registers WinPT's hot keys and allows to pass the GPG passphrase to WinPT. But what was my intention? I can just use KeePass's hot key functionality to pass the GPG password. However, I hate to startup up dozens of application which all occupy an icon in the system tray. This is even more true when I do not use the applications regularly. This was already the reason for my PuttyAgent plugin: No need to start both KeePass and pageant.exe. The same is true for KeePT: The main and unspectacular purpose of this plugin is to start WinPT (and hence GPG) from within KeePass. The minor purpose is to pass the GPG password from KeePass to WinPT. This plugin requires WinPT. At first, I wanted to compile WinPT into a DLL, just as I did it for PuttyAgent. But after spending hours in trying to compile the old WinPT code I gave up and decided to control the pre-compiled binary. This has another advantage: The plugin occupies only 80kB (written purely in C++ with WinAPI) whereas the whole WinPT (occupying 1-2MB!) is only loaded when needed.
How does the plugin work?
Basically, it displays WinPT's tray menu in the tray menu of KeePass ("KeePT...") and in the Tools menu. The menu is directly read form WinPT.exe. After selecting a menu entry, the plugin creates a new thread in which WinPT is started and the specific action launched.
Starting and exiting WinPT
The plugin searches for an existing WinPT instance and sends the commands to this instance first. If no instance is running, the plugin uses CreateProcess to execute WinPT. The path to WinPT.exe can be set in the plugin settings:
If the plugin started WinPT, there are two options: Either WinPT keeps running or the plugin waits until all dialogs from WinPT are closed and terminates the application again. This (default) behavior can be set in the settings (see screenshot) by: Close WinPT.exe if it was started by us.
Using WinPT hot keys
WinPT provides the option to set hot keys in the settings menu. KeePT can try to register these hot keys in the plugin settings with Try to register WinPT's global hot keys (see screenshot).
When this option is set, the plugin will read out the hot key configuration by WinPT from the registry, register the hot keys and pass them to WinPT (the same way as the action would be selected from the tray menu). Before starting WinPT, the hot keys are unregistered, such that they are registered by WinPT. This means: As soon as WinPT.exe is started by the plugin, the hot keys are processed by WinPT itself.
Note 1: When the option "Close WinPT.exe if it was started by us" is not used, this option should be avoided as well, since both WinPT and KeePT will try to register the hot keys. KeePT will display an error message in that the keys are already registered in this case.
Note 2: This option does not work with the portable version of GnuPT since the hot keys are not permanently stored in the registry in this case.
Note 3: The CTRL + ALT + F key (flushing the passphrase) is not supported by KeePT since WinPT does not provide a WM_COMMAND for that.
Passing the passphrase from KeePass to WinPT
In order to support passing the passphrase, the plugin injects itself into the running WinPT instance and overwrites the DialogBox API function which is used by WinPT to display the password dialog. In this case, a request is sent to the plugin and the plugin searches the KeePass database for an entry matching the key id. If it is found, the password is passed to WinPT. If there is an error, the default password dialog is displayed.
When the database is locked, the plugin attempts to unlock the workspace by displaying the master password dialog.
There might be cases when injecting the DLL into WinPT does not work. In this case, the plugin works except for passing the passphrase and an error message is displayed.
The GPG passphrase is found in the database by looking at the Notes-entry and finding a matching
entry where 0x022F21C2 represents the key id for the private key. The key id can be found in WinPT using the key manager column 'Key-ID or by decrypting a message with WinPT. WinPT then displays the key id which is used to decrypt this message.
Notes on Security
The plugin takes care of secure handling of the GPG password. The passphrase is not passed by WM_COPYDATA or any window message but rather by using shared memory. In order to avoid simple memory readouts, the shared memory is created using CreateFileMapping and MapViewOfFile rather than using "pragma data_seg" in the DLL. The principle is borrowed from PuTTY's Pageant: The injected WinPT first creates a FileMapping where the owner is explicitely set to the current SID and no further ACLs are set. This means that only processes of the same user can access the shared memory. WinPT then writes the key ID into this memory region and sends the name of the file mapping via WM_COPYDATA to KeePT. KeePT explicitely checks if the owner of the file mapping and the SID of the KeePass match. Afterwards the password is written into this region by KeePT. The memory for the passphrase is memset to 0x00 as soon as the password is not needed any more and in case of any errors.
Additionally, the plugin forces the page containing the password to reside in RAM by using VirtualLock (i.e., the page is never swapped out to disk).
Finally, the original password dialog of WinPT is used to allocate memory for the password. Basically, the WM_INITDIALOG is hooked, the password field is set by SetDlgItemText, which sends WM_SETTEXT and finally the OK button is pressed. The basic variant would send the password directly with SetDlgItemText. However, this trivially would reveal the password by Spy+. Instead, the memory is allocated by writing 0xFF spaces with SetDlgItemText and afterwards it is overwritten by the real password using memcpy.
Just copy the files to the program directory of KeePass and restart KeePass. The plugin can be configured in the plugin settings.
Please download the plugin from http://keepass.info/plugins.html.