If you’ve ever had an experience with Credential Providers in the past, you may think the title of this post is insane — it’s not.

I recently came across an interesting Github project that showed it was theoretically possible. I wanted to see if I could replicate the results myself without digging too deeply into how they did it. As it happens, I could.

I created a sample project that outlines how you can do it on Github: CredProvider.NET

.NET Credential Provider

Historically, Credential Providers have been complex components to write because they’re COM-based, and because they have weird restrictions you have to contend with since they run in the winlogon UI process. Both of these restrictions should make any sane developer run away — doubly so if you’re a .NET developer. However, if you’ve been around long enough, you may remember that COM-interop thing that makes it possible to call .NET code from COM components (and conversely, call COM components from .NET) and have the runtime do a whole host of evil to keep the two relatively stable.

The trick with interop is getting the interfaces right. Everything communicates through interfaces — it’s the only way to guarantee a stable contract between APIs. This is the crux of our implementation. You can codify them manually through MSDN definitions, but that’s error prone and not necessarily completely accurate. Thankfully, the Windows SDK contains an IDL file that defines the interfaces we need. All we need to do is convert them to something .NET understands. We do this in a two step process where we first compile the IDL to a type library, and then convert the type library to a .NET assembly.

You can compile a type library using the midl.exe tool. You’ll need to install the Windows SDK first though, otherwise you won’t have the IDL file.

midl "C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\um\credentialprovider.idl" 
-target NT62 /x64

You can see I’m using the latest 10.0.16299.0 build of the SDK. This particular version requires you explicitly target a version for some reason — older versions of this IDL don’t require the targeting.

This produces a few files, but most notably is the credentialprovider.tlb file. This is the type library. We need to convert this to an assembly. Normally, you’d just use tlbimp.exe, but it’s notoriously opinionated on how you talk to COM, leaving you stuck in a few ways (for instance, it expects you to throw exceptions instead of returning HRESULTs, despite the interface requiring you to return HRESULTs). It turns out the CLR Interop team built a set of tools to help you through this pain — specifically tlbimp2.exe (why they didn’t just ship this capability in the original tool is a mystery).

TlbImp2.exe credentialprovider.tlb /out:CredProvider.NET.Interop.dll 
/unsafe /verbose /preservesig namespace:CredProvider.NET

The key is the /preservesig parameter.

Once you’ve created the assembly, you can import it into a project and start creating your credential provider.

Credential Providers are made up of two core interfaces:

  • ICredentialProvider — Manages the interaction between the UI
  • ICredentialProviderCredential — tells the UI how to receive credentials from the user

There are a few related interfaces, but they are just there to enhance the capabilities of the credential provider. Once you implement your interfaces you need to decorate the class with some attributes to tell what’s exposed as COM implementations:

 

You only need to do this on the ICredentialProvider interface.

At this point you may notice a few annoying things. First, not all the interfaces are present in the assembly. A few interfaces were added in the Windows 8.0 timeframe, specifically the ICredentialProviderCredential2 interface, that allows you to follow the newer design guidelines. Second, some of the typedef’s don’t translate correctly. For instance, HBITMAP gets mangled. Fixing these issues requires a little surgery on the credentialprovider.idl file.

First, you need to move the library declaration to the beginning of the file. It’s already present somewhere in the middle of the file (search “library CredentialProviders”). Just move it to the beginning of the file so it includes all the extra interfaces. Second, find and replace any mangled pointer to HANDLE (e.g. HBITMAP* to HANDLE*). Now you’ll need to recompile with midl, and regenerate the library with tlbimp2.

You can see how I did it with this diff.

Unrelated, but you may notice a number of things were taken out. This is because I modified the file without making a backup (doh!), and had to search for the original online and could only find the first release (I suppose I could have just reinstalled the SDK, but that’s beside the point). Anyway, notice how there’s an ICredentialProviderCredential3? I suspect that’s how Windows Hello does the eye-of-Sauron graphic when it’s looking for you.

Windows Hello

You may also want to explicitly register for COM interop on build too. This will make the provider available on each build, but the downside is that it requires running Visual Studio as admin.

Register for COM interop

You need to tell Windows you’ve got a Credential Provider once it’s registered. You do this by adding it to the registry.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{00006d50-0000-0000-b090-00006b0b0000}]
@=”Credential Provider.NET”

Notice that the GUID matches the Guid in the class attribute. This is intentional. This tells Windows that the COM component with that given guid is a Credential Provider, and it should new-up an instance of it.

The other thing you’ll want to figure out is how to test this thing. You’ll notice all the images above show it being used within a user session, prompted via CredUIPromptForWindowsCredentials. This is intended because testing it on your own machine’s winlogon interface is an exercise in madness. Unhandled errors that cause your provider to crash will render the logonUI unusable and, well, you’re screwed. You have to boot into safe mode and remove the provider registration, but the provider is still loaded so you can’t log into safe mode! So you need to boot into recovery mode, and… — have you made a recovery image? Using CredUIPromptForWindowsCredentials will let you test your code easily and quickly, and it generally behaves like winlogon. Lastly, test it on a VM once it’s ready for more in depth testing.

And that’s all it takes to start writing a Credential Provider in .NET.

Some Notes

It’s worth noting that this is possibly (probably?) a bad idea. I don’t know how stable this will be in the wild.

Some References

I came across this Stack Overflow post in my attempts to figure out the ICredentialProviderCredential2 problem, which lead to this sample. Their recommendation to use tlbimp2 was a huge revelation.

Recently I created the Enclave.NET project, and it shipped with a simple in-memory storage service. It’s not particularly useful in it’s current form, so I created a sample a couple weeks ago that used Azure Key Vault as the storage and crypto service.

But Why?

Of course, you might be wondering why you’d want to use Enclave.NET this way, since Key Vault already provides isolation given that it’s hosted far away from your service. The obvious answer is that maybe you wouldn’t use it this way — it IS isolated enough. That said, this does provide you with some extra separation because your app now doesn’t have access to the secrets to connect to Key Vault — we’re working on the premise that every little bit helps.

And because it’s my project and my site and it seemed like a neat little idea. 😀

So how exactly does this work?

If you remember previously the service is supposed to be hosted locally, but outside of your own application, and relies on an HTTPS channel to offload data protection. That means we have a service host. In this case it’s just a console application. You’d likely want this running in a Windows service or Linux daemon in production so it’s not constantly having to spin up.

The service host looks for the settings.json file and spins up a web host given the provided server and client certificates.

You’ll also notice there’s a transform type that lets you setup your own services. This just injects the Key Vault storage and processing services.

You can find the KeyVaultStorageService and the KeyVaultCryptoProcessor in the sample project.

Once those are set, you can call the service from the client, and at this point the client has no idea where the keys are, or how they’re being used.

The neat thing about this is that it provides a great abstraction between the internal workings of the crypto bits, and the code that needs to protect data.

Recently I came across an interesting parameter of the New-SelfSignedCertificate PowerShell cmdlet — the -Signer parameter. This parameter allows you to provide a reference to an already-existing certificate that can be used to sign the newly-created certificate. This turns out to be an extremely useful little feature because sometimes you just need chained certificates to test stuff (so much so that I wrote a library that does this for me).

Not surprisingly, this cmdlet is much easier to use.

$ca = New-SelfSignedCertificate -DnsName "My Certificate Authority" -CertStoreLocation "cert:\LocalMachine\My"
New-SelfSignedCertificate -DnsName "child.domain.com" -CertStoreLocation "cert:\LocalMachine\My" -signer $ca

And voilà.

Signed Certificate

There’s a common problem that many applications run in to when executing cryptographic operations, and that’s the fact that the keys they use tend to exist within the application itself. This is problematic because there’s no protection of the keys — the keys are recoverable if you get a dump of the application memory, or you’re able to execute arbitrary code within the application. The solution to this problem is relatively straightforward — keep the keys out of the application.

In order for that to be effective you need to also move the crypto operations out of the application too. This means any attacks on the application won’t yield the keys. This is the fundamental design for services like Azure Key Vault, Amazon CloudHSM, or any other HSM service or device. In fact, even Windows subscribes to this design with CNG keys using LSASS.

I was thinking about this problem over the weekend and realized there isn’t really any good reference architecture out there that shows you how to build this design into your application. The services I mentioned earlier do great jobs at protecting secrets, but they’re kind of designed with certain applications in mind — greenfield, cloud first, or disconnected. This can make it difficult to migrate existing applications to use these services, or maybe you just can’t use them for whatever reason (regulatory, legal, etc.). On top of all that, you don’t even know how to start.

So, I did something dumb. I built a reference implementation that lets you move crypto operations out of your application and into a separate process.

Introducing: Enclave.NET.

READ THIS SECURITY WARNING

This is a reference implementation. That means it’s not designed to handle production loads, and absolutely is not built to withstand attack. It’s a sample intended to show how you might offload certain operations. There are probably some horrible bugs in here and there might even be vulnerabilities.

Was that sufficiently scary enough?

The basic idea is simple. You have an application that hosts a service. The service has a set of commands available to it:

  • Generate key
  • Encrypt
  • Decrypt
  • Sign
  • Validate

Your application calls these commands with the necessary payloads, the service does the thing, and returns a result. The service is HTTP-based, and protected with pinned client certificates.

The crypto operations are real, backed by the jose-jwt library, but they’re ephemeral — the keys are just stored in memory. The idea is that you can inject your own implementations as you see fit, so any migrations you might undergo can be gradual and painless.

There are two classes that need to be implemented — the crypto operations class, and the storage service. You can use the built-in crypto operations class InMemoryCryptoProcessor at your own risk, but you absolutely need to implement the storage, lest you lose all the keys when the app shuts down.

Crypto Processor

Storage Service

You can modify the startup code on your own, or you can implement IStartupTransform and configure it:

Calling the service is simple:

For more information take a look at the sample app.

Earlier we looked at how to build and package and then deploy nuget packages. One thing (of many) I glossed over was that whole version thing. It turns out versioning is really difficult to do. It’s kind of like naming things.

I’m not going to go into the virtues of one method (like semantic versioning) over others, but really just going to show how I set it up so my silly little project always has an incrementing version number after build.

First, I created two new build variables “MajorVersion” and “MinorVersion”, setting their values to match the current static version.

Set the Variables

Once the variables were set I could use them to set the BuildNumber variable in the build options.

Set the Build Number

This uses the major and minor as the static values created earlier, the current month/day for the build, and the revision number for the build revision. This’ll generate a value along the lines of 1.5.0819.1 and will increment to 1.5.0819.2 until tomorrow, which’ll bump up to 1.5.0820.1, etc. Yes, I’m a monster.

With the build number defined we can configure the build task to explicitly set the Version property with -p:Version=$(Build.BuildNumber).

Set Build Version

Now any new builds will use this version format. This way I don’t have to worry about forgetting to increment the build numbers on small fixes and releases. I still have to increment the major and minor versions when anything big is released, but that’s reasonable and expected.