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.
r04r meinte …
<comment date="2012-01-10T23:31:42Z" name="r04r" url="http://minichan.org"> Would it be possible to get this plugin for KeePass 2.x? </comment>
Niki meinte …
<comment date="2012-01-11T08:44:27Z" name="Niki"> Hi r04r,
Unfortunately the plugin is only available for KeePass 1 since I am only using KP1.
The plugin interface for KP2 is fundamentally different (based in C#/managed code) and provides different APIs, so it is a hard task to port the plugin. Maybe I will switch to KP2 myself one time, then I will probably port the plugin. Also when there are many inquiries for KP2, I may consider porting it.
r04r meinte …
<comment date="2012-01-11T10:45:19Z" name="r04r" url="http://minichan.org"> Hello Niki,
Thank you for the input and I was afraid that might be the case. This plugin and the SSH Agent one look really useful so that's too bad. May I ask why you're sticking with KP1? </comment>
Niki meinte …
<comment date="2012-01-11T13:29:24Z" name="Niki"> Hi,
In general, KP2 is more "bloat" because it is based on .NET, C# and is slower. The features in KP2 are great but I can life without them.
My main reason is that for KP1 I have a port for my mobile phone (Windows Mobile) which is a main requirement for me. Ironically, KP1 seems to be more future-proof for me (personally) because there is a Linux port (KeePassX) and an Android port, should I buy a new phone.
The final decision for me to use KP1 gave me the author himself where he assured multiple times that KP1 is not being discontinued and there are no plans to do so. KP1 is just a kind of "KP lite". KP2 was made because of all these new requested features which required a complete redesign. As the author told me, he even is using KP1 for himself!
Last but not least, KP1 seems to be used in enterprise environments and it is also used in my company (a well known IC manufacturer with 40k employees worldwide).
pete meinte …
<comment date="2012-12-10T14:49:13Z" name="pete"> We use KP2 at work, due to its ability to handle multiple users accessing 1 database </comment>
Josch meinte …
<comment date="2015-07-21T14:45:26Z" name="Josch"> Hi ro4r, any changes on the KP1-Policy with you :)
Regards, Josch </comment>
Niki meinte …
<comment date="2015-07-21T20:17:59Z" name="Niki"> Hi Josh,
Indeed, there are changes (for me at least, don't know for ro4r ;-) ).
I switched to KP2 some time ago and and even created some (actually simple) plugins already: http://niki.hammler.net/wiki/KeePass (more of them started but unfinished).
I also wanted to port the KeePT plugin already (and started) but it seems to be non-trivial because I need to load a 32 bit DLL into a possibly 64 bit process (.NET). Also my time is rather limited.
But if I see that other people would also use it this would motivate me to put more emphasis on it ;-)