Open JeremyRand opened 4 years ago
Relevant Registry values:
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CertDllCreateCertificateChainEngine\Config\PinRules
: This is the Admin
(AKA Enterprise
) pin rules value.HKLM\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\AutoUpdate\PinRulesEncodedCtl
: This is the AutoUpdate
(AKA AuthRoot
) pin rules value.Registry values that look potentially relevant but which I haven't looked at much:
HKLM\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\AutoUpdate\HpkpEncodedCtl
: This appears to be a pin rules value for HPKP (HTTPS Public Key Pinning)?Registry values that look likely to not be relevant, but which I haven't looked at much:
HKLM\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\AutoUpdate\DisallowedEncodedCtl
: This appears to be equivalent to the Disallowed
logical store, but as a CTL.HKLM\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\AutoUpdate\EncodedCtl
: This appears to be equivalent to the AuthRoot
logical store, but as a CTL.Because both Admin and AutoUpdate consist of only a single Registry value, we will need to merge the command-line-supplied pin rules into the existing value that's in the Registry.
A good start for this would be to write a Go library that parses the Registry value into a high-level struct. I believe the Registry value is ASN.1-encoded; Go's standard library should be able to parse ASN.1.
Some Microsoft docs on the XML format, and how to convert XML to ASN.1, are at https://docs.microsoft.com/en-us/windows/security/identity-protection/enterprise-certificate-pinning . Note that running certutil
with the -v
flag will give you more verbose output about the ASN.1 data. Some of the non-obvious fields that I've deduced are:
You can view the key ID hashes of a cert by passing the DER-encoded cert to certutil -dump
. I am not certain exactly what the "key ID hash" is taking the hash of.
Note that we do not want to have a dependency on certutil
or any other Microsoft programs/libs in the final code we produce, but it's fine to use that stuff for debugging/experimenting.
Based on hacking around with a hex editor, changing the error code to arbitrary CryptoAPI error codes seems to work fine, in the sense that CryptoAPI will return the specified error code. (ECP doesn't seem to enforce any kind of whitelist.) However, some error codes will confuse the heck out of some software that isn't expecting to encounter them (I found one error code that appears to cause PowerShell to get stuck in an infinite loop). I didn't extensively bruteforce the set of error codes; this might be useful to automate once we have a Go library for this.
We should support Enterprise Certificate Pinning as a 3rd store type (in addition to CryptoAPI and NSS).