Strong key protection is one of the most misunderstood features in Windows security. In this post I will attempt to demystify it. I will also try to address some of the misconceptions about this feature that I’ve come across on the security discussion lists and while assisting our support folks.
It all starts with Crypto… API Framework
Windows has two crypto API frameworks for persisting public/private key pairs. First one called Cryptographic API or CAPI and the second one called Cryptography Next Generation or CNG. Both define a set of flags for their APIs that can set extra levels of protection. Let’s call them Medium and High for the sake of this discussion.
The flags are CRYPT_USER_PROTECTED (Medium) and CRYPT_FORCE_KEY_PROTECTION_HIGH (High) passed to the CryptGenKey function in CAPI. In CNG, the flags are NCRYPT_UI_PROTECT_KEY_FLAG (Medium) and NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG (High) actually set on the NCRYPT_UI_POLICY structure that is used during a call to the NCryptSetProperty function. The same flags can be used during import of the key with CAPI and CNG.
It all starts with Crypto… Providers
It is important to understand that the API model itself doesn’t define what those flags actually mean or what it means when they are not used. A developer that implements a provider for these APIs makes that decision. For example, a particular provider can require whoever is trying to use a key to solve a Sudoku puzzle where difficulty goes up as the Medium and High protection is used.
Providers are modules that plug-in into the API framework and are actually responsible for key material storage and protection. In CAPI world providers were called Cryptographic Service Providers (CSPs) and in CNG they are called Key Storage Providers (KSPs). A provider could be purely software-based (for example Microsoft Windows in-box providers) or a hybrid of software and hardware (for example Smart Card or Hardware Security Module (HSM) provider).
Microsoft Provider Implementation
From Windows Vista/Windows Server 2008 on, Windows ships with a handful of CAPI and CNG software-based providers while earlier Windows versions are only supporting CAPI. Those providers implement key protection in a very similar way in respect to the strong key protection.
By default all private keys stored by Windows providers are protected by using DPAPI. See this MSDN article Windows Data Protection or this Microsoft Knowledge Base article How to troubleshoot the Data Protection API (DPAPI) on more details about DPAPI. The two higher levels of protection Windows providers use are “consent” and “password”; however, they don’t simply map to the flags we talked about earlier.
First let me describe what these two options mean and then I’ll explain how they map to the flags. A consent option simply prompts a user asking her to allow access to the private key by an application that is running on behalf of that user. This helps to prevent some rogue application quietly using somebody’s key.
The password protection actually asks a user for password that is used as additional entropy passed to the DPAPI. User selects the password when a key is created (by the way password complexity policy on the machine applies to this password) and has to provide it before a key can be used. Not only this setting provides the same protection as the consent setting, it also helps against attacks when a user logon credentials have been compromised.
Now back to the Medium and High… With medium protection a user is presented with a UI choice between consent and password when a key is created. User has to select either one of them before the key is created and will be required to either consent or provide the password, depending on user’s choice at the create step. With high protection a user is presented with UI where the only choice is to create a password for the key.
A picture worth a thousand words so let’s take a look at the UI involved. This is what you see for a CAPI key with Microsoft software providers when CRYPT_USER_PROTECTED flag is passed (this is by the way is part of the DPAPI and is also documented in the MSDN article referenced earlier):
This is the first dialog that user sees. By clicking on the “Set Security Level…” a user can select the desired level from the following dialog.
When an application tries to use the key, the following dialog is presented.
Now let’s take a look at how things change when CRYPT_FORCE_KEY_PROTECTION_HIGH is used.
First noticeable different is that the default level is set to high already. Also, the OK button is disabled because no password has been entered. When a user clicks on the “Set Security Level…” they see the following UI.
This time user gets no option between Medium and High and is taken straight to the password selection page. When an application tries to use a key protected by a password the following UI is presented:
I will not go into the “Remember password” option in this post because it is better to discuss it together with the caching that Microsoft providers support and that is enough for a post on its own.
Now let’s see what CNG UI looks like. When you create a key pair and set its UI policy with the NCRYPT_UI_PROTECT_KEY_FLAG flag, you will see this UI:
Conceptually it is very similar to UI CAPI providers show. It is still allows a user to select between consent and password. One difference I’d like to point out is that default is actually password.
When an application tries to use a key that was created to require consent, they see this dialog.
With the NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG flag the creation dialog only allows password to be used.
When a key is being used, users will see this dialog (note the text box to enter password):
Security policy for strong key protection
Now that we identified what each flag does with respect to Windows in-box crypto providers, lets break down what affects “System Cryptography: Force strong key protection for user keys stored on the computer” policy has. The policy I’m talking about can be found in Group Policy under Local Policies\Security Options node and it affects different components of windows differently. The policy has these options (I will give them short names to use later in the text):
1. NoImput – User input is not required when new keys are stored and used.
2. Prompt – User is prompted when the key is first used.
3. Password – User must enter a password each time they use a key.
Note none of these simply map to flags discussed above.
Windows in-box providers only react to the “Password” setting of this policy by behaving as if High protection was requested when application requests Medium. For example, if an application passed NCRYPT_UI_PROTECT_KEY_FLAG and the policy is configured to “Password”, Windows CNG provider will behave as if NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG was used instead (same apples to CAPI Windows providers). The “Prompt” setting has no effect.
Certificate Enrollment Behavior
When enrolling for certificates from a Windows Enterprise CA using certificate templates (http://go.microsoft.com/fwlink/?LinkID=92522), administrators can select an option “Prompt the user during enrollment and require user input when the private key is used” on the Request tab. If this option is not selected, the strong key group policy doesn’t affect how keys are created during certificate enrollment. However, if this option is selected, the certificate enrollment wizard (one that can be launched from Certificate Manager snap-in certmgr.msc) will automatically check the “Strong private key protection” option which in turn will result in CRYPT_USER_PROTECTED or NCRYPT_UI_PROTECT_KEY_FLAG flag used during key generation. So if the Group Policy was set to “Password” the user will be presented with a dialog box requiring her to enter the password (remember Provider Behavior), otherwise she will get a choice between consent and password options.
Certificate Import Wizard Behavior
When you import a certificate, the certificate template setting “Prompt the user during enrollment and require user input when the private key is used” is not considered even if that certificate is based on some template. On one of the pages of the wizard, user has an ability to check if strong key protection should be used. If Group Policy was set to “Prompt” option, the wizard will check that option by default. If the Group Policy was set to “Password” option, the wizard will check the option and disable the checkbox control preventing user from unchecking it.
Certutil.exe –importPFX Command Behavior
Until Windows 7 and Windows Server 2008 R2 there was no way to force strong key protection while importing a certificate from a PFX file using Certutil.exe -importPFX command. Now you can supply ‘-protect’ option with the command that in turn will pass CRYPT_USER_PROTECTED or NCRYPT_UI_PROTECT_KEY_FLAG flags to the provider being used to import the key. After that, the Group Policy setting will have the same effect as I described in “Provider Behavior” section above.
More About That Certificate Template Setting
I have briefly mentioned the certificate template setting “Prompt the user during enrollment and require user input when the private key is used”. I want to discuss the level of security of this setting. The fact is that there is none. The CA has no way to enforce that the client did anything in response to this setting on the certificate template. Windows tools that do certificate enrollment such as Certificate Manager snapin, certreq.exe, and our APIs will honor it, but there is no real security protection against some other tool ignoring it. This holds true with all other certificate template settings that have to do with private key properties except the key size which can be verified based on the certificate request and public key that is part of it, but this topic is good for another post. One thing you can take away from this is that if you want high level of security, use hardware key storage (smart card or HSM) and enroll on machine you control with some Enrollment Agent (EA) present during enrollment. Otherwise this setting is just to keep honest people honest.
How can you find out what protection is set on the key
So how can you find out if a key associated with some certificate has strong key protection enabled? One way would be to use certutil.exe -store command that performs a key operation on each certificate it enumerates. If the key has high protection set, the UI will be displayed.