Improvements in Windows Kerberos Architecture
It's Friday afternoon, it's sunny out, and I have no desire to start on any new projects this late in the week.
Let's discuss architectural changes to Kerberos cryptography in Windows!
Twitter warning: Like all good things this is mostly correct, with a few details fuzzier than others for reasons: a) details are hard on twitter; b) details are fudged for greater clarity; c) maybe I'm just dumb.
Why do you care? You don't.
Will this practically affect you? No, it won't.
Is it interesting? Well, I think it is.
Anyway...
Many many moons ago Kerberos in Windows supported only RC4 and DES algorithms for the various encryption and signing requirements.
Because of this there was a useful dichotomy of things. Code was easy enough. Was it doing RC4? Yes, carry on. No? do DES.
This meant you could reason about all the different facilities of Kerberos fairly easily because whatever you were doing only needed to know two states.
This actually worked relatively well for a while because technically you could bolt on 3rd party encryption algorithms, and they'd more or less just work as long as they followed either the DES way or the RC4 way.
This was manifested through the CDLocateCSystem and family of cryptdll.dll library functions.
These are undocumented functions, and they certainly were never intended for 3rd parties to use.
Nevertheless.
This all came about in the late 90's for the release of Windows 2000 and went along without issue until Vista/Server 2008 because: AES.
AES was an important milestone because it was and still is a solid crypto suite.
Bringing AES into the picture wasn't that difficult at a low level. There's that cryptdll.dll thing and it exports all the usual functions you'd expect like "please gimme all the crypto suites you support" and "I've chosen AES, please give me the encryptor for that".
On top of that, AES also met the standard that it more or less behaved like RC4 or DES, so it fell into the do-as-DES-does flow of logic.
Beautiful. Life is good.
Ah, but DES is shit. We also need to kill DES quickly and quietly.
Okay, find and replace "DES" with "AES" and life is good, right?
Nah, we also need to continue supporting DES for those ERP systems that only support DES, but never willingly choose DES normally.
Okay, so do AES or RC4, or DES if DESONLY, and if AES follow the DES logic for etype-info and salts and such.
Oh, also AES can only be used on Server 2008 DFL because reasons.
Uhhhhhhhhhhh. K.
And so, this monstruous pattern was born (paraphrased, not real source code).
That's ehh not great. Doubly so when it's duplicated in subtly different ways a few dozen times throughout the code.
It's ugly, but manageable enough so long as you don't have to futz with the logic, and it has worked just fine for 20 years.
Okay, but what happens if you need to kill off another cipher suite because, say, a researcher finds a flaw in how checksumming is handled. 😶😬
Welp.
We *could* just add in checks everywhere for DES... and RC4. It's clunky, but it's not the end of the world.
We could just remove RC4 from the cryptdll implementation.
Yeah nah, that is the end of the world.
Let's look at the cards dealt to us.
DES -- dead, removed in future version.
RC4 -- dying, removed in future version.
AES-SHA1 -- alive, bit ornery, not going anywhere.
That's actually not a great hand. We need to get better cards at some point. We have options, which in the simplest terms is RFC 8009 -- AES-SHA2.
But how do we add that? More important how do we add that AND also remove RC4?
That's right kids! We rewrite the entire crypto stack in Kerberos!
Hey look at that.
The value here is significant because we can (and did) rewrite all the monstrous logic spread throughout the codebase into logic that never has to be touched ever again.
This means all the logic to disable a cipher outright like DES, or disable certain usages of the cipher, like RC4 session keys, is hidden from the rest of the stack.
On top of that, adding a *new* cipher suite is relatively trivial because only one spot in the code needs to know.
And most importantly I get to delete functions like this.