Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R&D: Better support for Windows cert registry blobs #124

Open
JeremyRand opened this issue Apr 4, 2020 · 24 comments
Open

R&D: Better support for Windows cert registry blobs #124

JeremyRand opened this issue Apr 4, 2020 · 24 comments

Comments

@JeremyRand
Copy link
Member

JeremyRand commented Apr 4, 2020

Windows stores its certificate trust policy in the Registry. The format is not fully documented, but I've reverse-engineered a decent amount of it. ncdns has a partial serializer implementation as part of the certinject package, but it's missing quite a lot of functionality. Examples of functionality that's missing:

  • Support for registry keys besides the Root CA list in the Enterprise Certificates store. Initial attempts at reverse-engineering indicate that other keys are likely to be useful, e.g. the Intermediate CA list (relevant to Namecoin's Constrained certificate form for positive overrides), the Prohibited cert list (might be combinable with crosssignnameconstraint to yield negative overrides), and the Built-In Certificates store (might be combinable with external name constraints to yield negative overrides).
  • Support for certificate properties besides the DER encoding property. Initial attempts at reverse-engineering indicate that other properties are likely to be useful, e.g. the external EKU property (might be able to disallow Namecoin TLS certs from being used for non-TLS use cases, and might also be combinable with crosssignnameconstraint to yield negative overrides) and the external name constraints property (might yield negative overrides, and might be able to disallow the Namecoin root CA from being able to sign non-Namecoin certs).
  • Support for Enterprise Certificate Pinning (ECP) policy. This might yield a useful approach for negative overrides. In particular, it would be interesting to analyze whether the cert blob format permits us to set a cert pin on a TLD, which would yield a major speed and privacy boost for Namecoin. (Microsoft's command-line tools do not appear to support this, but it is not clear whether this is a CryptoAPI limitation or just a limitation of Microsoft's serialization code.) It would also be interesting to analyze whether the cert blob format can be rigged to facilitate enforcement against Chromium, which doesn't seem to honor ECP policy.
  • A command-line certinject tool. (Right now we just have a Go library, which is not particularly convenient for us to experiment with)

It would be highly useful to implement some or all of the missing functionality in Go, so that we can experiment with that functionality and determine what functionality may be useful for Namecoin going forward.

@JeremyRand
Copy link
Member Author

@domob1812 Are we able to use Handshake funds for this? I suspect that a week of dev time (Aerth and I would probably collaborate on it) would yield some useful progress, and we could evaluate at that point whether additional dev time would be productive.

(Unlike namecoin/electrum-nmc#216 , this task is not time-sensitive since there are no 3rd-party deadlines involved.)

@domob1812
Copy link
Collaborator

Yes sure, fine with me. (Although I wonder why it is needed to reverse engineer this? If there is no proper documentation / existing APIs, are 3rd-party applications like ncdns actually supposed to touch this at all?)

@JeremyRand
Copy link
Member Author

(Although I wonder why it is needed to reverse engineer this? If there is no proper documentation / existing APIs, are 3rd-party applications like ncdns actually supposed to touch this at all?)

@domob1812 I'm not aware of any TLS implementations that deliberately expose API's to users for the kinds of things that Namecoin requires. Unfortunately, the kinds of things Namecoin does generally require subverting API's that are intended for only the TLS implementation vendor to use internally. Interestingly, Microsoft seems to be one of the best vendors in terms of having API's that can be subverted to do what we want, even though those API's are internal and mostly undocumented.

@JeremyRand
Copy link
Member Author

1 week of development has been completed. Here's what's been accomplished so far:

  • Create separate Git repo for certinject.
  • Command-line utility for certinject.
  • Support for logical stores other than Root.
  • Support for physical stores other than Enterprise.
  • Travis CI integration tests that verify that injecting a self-signed end-entity cert to Root has the intended effect (making it be accepted as a trusted TLS server cert) in Windows Powershell.

I will send payout info via a private channel.

@domob1812 Are we able to allocate Handshake funding to a 2nd 1-week block of development? Likely work candidates for the 2nd 1-week block:

  • More integration tests (e.g. tests for non-Root logical stores, and tests for CA certs).
  • Support for certificate properties besides the DER encoding property.
  • Support for Enterprise Certificate Pinning (ECP) policy.
  • Make ncdns use the new certinject package.

@JeremyRand
Copy link
Member Author

I will send payout info via a private channel.

Info sent via a private channel.

@domob1812
Copy link
Collaborator

@JeremyRand Yes, I think another week of development is fine. How much more wlil be needed to "finalise" this project? Will the second week be enough (looks like it from the description you provided)?

@JeremyRand
Copy link
Member Author

@domob1812 Work on negative overrides for Windows is currently on hold while we work out some details with Microsoft developers. In the meantime, is it okay to use the 2nd week of development for other ways of injecting certs into the Intermediate CA list (besides the certinject codebase)? There are indications that we can do this in a way that has better performance on Windows than certinject, and also happens to be cross-platform (should work in mainstream browsers on macOS, GNU/Linux, and maybe Android and iOS, without platform-specific code changes). AFAICT it appears to be in scope since Intermediate CA list injection is covered (even though it's a different codebase), but figured I should check rather than assume.

How much more wlil be needed to "finalise" this project? Will the second week be enough (looks like it from the description you provided)?

The 2nd week should yield major progress, but hard to be sure whether it's going to be final (in large part due to the ongoing discussion with Microsoft that doesn't have clear conclusions yet).

@domob1812
Copy link
Collaborator

Yeah sure, fine with me.

@JeremyRand
Copy link
Member Author

JeremyRand commented Oct 6, 2020

Okay, we're nearing the end of the 2nd week of development. Development focused on the Extended Key Usage and Name Constraints properties in CryptoAPI blobs. Here's a summary of what's been accomplished in the 2nd week:

  • We can apply an Extended Key Usage property when injecting a cert to a CryptoAPI trust store. Among other things, this should be useful for preventing a Namecoin TLS CA from signing certs that aren't TLS server certs. Injecting the cert and applying the EKU property are an atomic operation.
  • We can apply a Name Constraints property when injecting a cert to a CryptoAPI trust store. Among other things, this should be useful for negative overrides, and also should be useful for preventing a Namecoin TLS CA from signing certs for non-Namecoin domain names. Injecting the cert and applying the EKU property are an atomic operation.
  • As components of the above 2 things, we can serialize a CryptoAPI cert blob from a list of arbitrary properties, and we can extract arbitrary ASN.1-encoded X.509 extensions from certs that the Golang standard library produces.
  • We have integration tests for both the EKU and NC properties on Travis CI.
  • We have integration tests for injecting a root CA. (Previously we only tested injecting an end-entity certificate.)
  • The existing certinject integration tests have gotten an overhaul; most notably, we now run each TLS handshake in a separate process, to prevent cert verification results from being cached. (The previously existing tests only worked by dumb luck, because the "TLS handshake should succeed" tests were after the "TLS handshake should fail" tests.)
  • There was also some other stuff done in the 2nd week that cannot yet be disclosed on a public issue tracker; I can comment on this via private channels.

If we fund a 3rd week, I would probably try to focus on functionality that can leverage the Name Constraints property to do negative overrides. E.g. injecting the property to existing certs (rather than injecting new certs), and enumerating certs from the trust store rather than making the user pick a single cert. If extra time remains, then the cross-platform intermediate CA injection that I mentioned previously seems like a good thing to pursue.

@domob1812 Are we able to fund a 3rd week of dev with Handshake funds?

@domob1812
Copy link
Collaborator

No objections from my side, but can we already estimate how much funds wlll be needed to fully complete this?

@JeremyRand
Copy link
Member Author

can we already estimate how much funds wlll be needed to fully complete this?

@domob1812 For negative overrides via the Name Constraints property, I think we've basically exited the "research" phase (we've confirmed that it works), and entered the implementation phase (now all we really need to do is code up a user-friendly application that automates the procedure of using it for Namecoin purposes). The one exception here is that we're still in the "research" phase for namecoin/certinject#23 (I suspect I know an easy way to do it, as mentioned in that issue, but we haven't confirmed this).

I suspect that we could get an application written for Namecoin negative overrides via the Name Constraints property within a week, and integrate it into the ncdns installer within another week, although these estimates are fuzzy. In practice all of my estimates seem to be either highballs or lowballs, and it's never easy to guess which will be which.

@JeremyRand
Copy link
Member Author

Weeks 2 and 3 have completed.

What we got done in Week 2:

  • Everything listed in R&D: Better support for Windows cert registry blobs #124 (comment)
  • Researched syncing the Windows AuthRoot.stl with the AuthRoot logical store; this is needed in order to apply a Name Constraints property to a root CA that Windows trusts by default but doesn't include the cert for by default. (Only a few root CA's have their certs bundled with Windows.)
  • Added certinject integration tests for the Disallowed logical store, which is used to mark certs as revoked (similar to the NSS "Prohibited" trust flag).
  • Added certinject integration tests for the AuthRoot logical store; this is used for root CA's that are shipped to Windows users via Windows Update.
  • Started adding certinject integration tests for the enterprise and group-policy physical stores; these are used for distributing certs via Active Directory and Group Policy.

What we got done in Week 3:

  • Finished adding certinject integration tests for the enterprise and group-policy physical stores; these are used for distributing certs via Active Directory and Group Policy.
  • Implemented AuthRoot.stl syncing; this is needed in order to apply a Name Constraints property to a root CA that Windows trusts by default but doesn't include the cert for by default. (Only a few root CA's have their certs bundled with Windows.)
  • Support editing existing blobs; this enables us to apply EKU or Name Constraints properties to existing CA's without nuking whatever properties they might already have. The existing EKU and Name Constraints properties are still nuked if new EKU or Name Constraints data is provided, though.
  • Support searching for blobs by SHA1 hash instead of preimage. Makes it easier to edit a certificate that's already in the store.
  • Support applying the requested EKU or Name Constraints operations to all certs in a given store. Required for negative overrides for Namecoin (we apply a Name Constraints property to all built-in root CA's).
  • Added Name Constraints injection to the ncdns Windows installer. Not yet sandboxed; only runs once on install.
  • Added AuthRoot.stl syncing to the ncdns Windows installer. Not yet sandboxed; only runs once on install.
  • NSIS research for improving the TLS installation in the Windows installer.
  • Removed old tlsrestrictchromium support from NSIS installer; AFAICT Chromium no longer supports loading key pins from TransportSecurity. It's replaced by the Name Constraints property.
  • More static analysis fixes for certinject.
  • Partial support for nightly builds of certinject; makes QA testing easier. The nightly builds functionality should be pretty easy to port to our other Go projects e.g. ncdns.

If we fund a 4th week, I'd probably do the following:

  • Some final cleanup on the certinject support (in particular, the Magic tagging feature needs tweaking, because right now it applies a "Namecoin Dehydrated Certificate" Magic tag to all the built-in root CA's, which will cause Bad Things ™️ to happen when ncdns's "delete expired certificates" code sees them).
  • Finish setting up certinject nightly builds. (Should be quite easy.)
  • Get a new ncdns release out that includes negative overrides via certinject and AuthRoot.stl.
  • Move on to cross-platform intermediate CA injection (positive overrides).
  • If cross-platform intermediate CA injection gets finished ahead of schedule, come back to certinject and AuthRoot.stl to add more reliable sandboxing/syncing. There's a decent amount of stuff here that we can improve, but IMO it's less important than intermediate CA injection, so I'm not going to worry about it too much.

@domob1812 Is it okay to pay out for Weeks 2 and 3? (If so, I'll send payment info via a secure channel.)

@domob1812
Copy link
Collaborator

Yes sure.

@JeremyRand
Copy link
Member Author

Payment for Weeks 2 and 3 received, thanks!

If we fund a 4th week, I'd probably do the following:

  • Some final cleanup on the certinject support (in particular, the Magic tagging feature needs tweaking, because right now it applies a "Namecoin Dehydrated Certificate" Magic tag to all the built-in root CA's, which will cause Bad Things tm to happen when ncdns's "delete expired certificates" code sees them).
  • Finish setting up certinject nightly builds. (Should be quite easy.)
  • Get a new ncdns release out that includes negative overrides via certinject and AuthRoot.stl.
  • Move on to cross-platform intermediate CA injection (positive overrides).
  • If cross-platform intermediate CA injection gets finished ahead of schedule, come back to certinject and AuthRoot.stl to add more reliable sandboxing/syncing. There's a decent amount of stuff here that we can improve, but IMO it's less important than intermediate CA injection, so I'm not going to worry about it too much.

@domob1812 Can we authorize funding Week 4?

@domob1812
Copy link
Collaborator

@JeremyRand Do I see it correctly that with week 4, we will be getting all of this released in ncdns? Or would there still be work required afterwards?

Funding week 4 seems fine from my point of view.

@JeremyRand
Copy link
Member Author

@JeremyRand Do I see it correctly that with week 4, we will be getting all of this released in ncdns? Or would there still be work required afterwards?

@domob1812 The negative overrides for Windows via certinject+AuthRoot.stl are expected to be released in the ncdns NSIS installer as part of Week 4, although there may be some corner-cutting involved that we can come back to for cleanup in the future. For example, the installer will probably wipe any of the pre-existing name constraints that are imposed on built-in CA's. This is not likely to be a problem in practice, because Microsoft doesn't use that feature anywhere, nor can I find any DDG or GitHub hits for anyone besides us who are using that feature, so it's not a big deal. Future cleanup can fix this, but since it's an edge case that is not going to happen in the real world, I don't want to focus too much on it.

It is not yet clear whether we'll get the cross-platform positive overrides via intermediate CA injection finished during Week 4. The initial experiments that I did to verify that the concept was workable (presented at the Grayhat 2020 Monero Village) were pretty simple (maybe a day or two of hacking), so maybe we can get it released in Week 4, but the Grayhat experiments cut a lot of corners, and I don't know yet whether doing this stuff cleanly will take much longer. And of course then there's the question of what "released in ncdns" really means, in the sense that this code would be theoretically cross-platform, but ncdns does not have any kind of installer codebase except on Windows. I would certainly focus on adding it to the ncdns Windows installer before messing with other platforms, but it's definitely something that I'd want to package for macOS and GNU/Linux as well, when time+funding is available to do so. So, in summary I don't know if it'll be released in the Windows NSIS installer for ncdns as part of Week 4 like the negative overrides will be, but I'd expect major progress, and more likely than not, we can at least get non-installer binaries (probably for all 3 major platforms) of the relevant code published so that QA testers can have fun with it.

@JeremyRand
Copy link
Member Author

Funding week 4 seems fine from my point of view.

@domob1812 Week 4 has been completed. This week was mostly a compilation of miscellaneous small tasks that were needed as prereqs to actually do a new ncdns release. Here's what was accomplished:

  • More code cleanup in certinject
  • More experimentation with CTLPop; replace the PowerShell CTLPop implementation with a certutil one-liner that I was able to dig up from the Microsoft docs.
  • Port our certificate code from x509-signature-splice to SpliceSigner, as per recommendation from Filippo Valsorda. This allows our Go code to work properly without maintaining a fork of the Go standard library. It also allows our Go code to build properly in modern versions of Go (our stdlib fork didn't build in newer Go releases).
  • Fix a nightly build issue where artifacts were getting double-gzipped.
  • Cleanup nightly build code for certinject and ncdns-nsis.
  • Support configurable Magic Tags in certinject. This prevents certinject from conflicting with ncdns, and also opens the door to using certinject to restrict enterprise CA's.
  • Release ncdns v0.1 (binaries are uploaded and blogpost is written; it's in the publishing queue).

As a bonus, I threw in some research on TLS support in GnuTLS and OpenSSL. I dug up significant info about both of them, which should help us support those libraries in the future.

@domob1812 Is it okay to pay out for Week 4?

If funding Week 5 is approved, I intend to first focus on cross-platform intermediate CA injection (positive overrides via Encaya). If that's done ahead of schedule, I will probably work on modifying ncp11 (which handles TLS support for Firefox and Tor Browser) to work properly with the Encaya certificate form (the first step of which is to refactor ncp11 and its pkcs11mod library to use the higher-level p11 library, which will make the code a lot more maintainable).

@domob1812 Is it okay to allocate Handshake funds for Week 5?

@domob1812
Copy link
Collaborator

Paying out week 4 is fine for me.

To be honest, I have no clue what Encaya is. Can you give a bit more context of what week 5 would give in addition to what we already have (which as far as I understand, already is fully working certificate injection)?

@JeremyRand
Copy link
Member Author

To be honest, I have no clue what Encaya is. Can you give a bit more context of what week 5 would give in addition to what we already have (which as far as I understand, already is fully working certificate injection)?

@domob1812 Ah, sorry for being unclear, I forgot that you don't hang out on IRC and probably didn't see my Grayhat talk from a few months ago about this. So there are 2 different use cases for cert injection: positive overrides (making Namecoin certs be accepted by browsers without an error if they match the blockchain) and negative overrides (making certs issued by a public CA be rejected by browsers if they purport to be for a Namecoin domain but don't match the blockchain). These are mainly orthogonal, and tend to use totally different code paths. The certinject codebase was originally written to do positive overrides, but has been repurposed (as part of this issue) to do negative overrides (via injecting the Name Constraints Property to existing CA's). While the certinject codebase is technically usable for positive overrides, and ncdns currently supports this, that usage is deprecated for the following reasons (among others):

  • Only works on Windows.
  • Requires elevated permissions to run (specifically, it needs the ability to add arbitrary certs to root CA list, which is a security risk since it could add certs for non-Namecoin sites), and requires real-time access to the cert store.
  • Only works with the dehydrated cert form, which is incompatible with the cert forms that work in Firefox-based browsers. So a website can support either Chromium or Firefox but not both, which is bad.
  • Uses a lot of blockchain storage -- enough that putting 2 certs into the chain at once in order to smoothly rotate certs is difficult.

Encaya is a new approach to positive overrides, which has the following benefits (among others):

  • Works with anything that supports AIA, meaning it'll work with any application that uses Windows for cert verification, as well as Chromium and Safari on all mobile and desktop OS's.
  • Doesn't require elevated privs at run-time; the run-time code is sandboxed to only be able to issue certs for .bit domains; the run-time code can run on a different machine than the browser.
  • Uses a cert form that is compatible with Firefox-based browsers, so a given website will be able to support both Chromium and Firefox.
  • Uses less blockchain storage (because it avoids encoding the validity period and the ECDSA signature in the blockchain, and also supports layer-2 for issuing new certs without touching the blockchain).

So, the ncdns release that we just did implements negative overrides via certinject; the next step is to get positive overrides implemented via Encaya. That's what I'm suggesting Week 5 be allocated to. Hope that makes more sense. :)

@domob1812
Copy link
Collaborator

Yes, it does. I'm definitely fine spending another week on getting this to work with all the advantages you listed. :)

Just out of curiosity, why did we even go for the previous weeks with certinject if it is deprecated and to be replaced now anyway?

@JeremyRand
Copy link
Member Author

Just out of curiosity, why did we even go for the previous weeks with certinject if it is deprecated and to be replaced now anyway?

@domob1812 The vast majority of the certinject work covered in this issue is specifically for the negative override functionality, which is not deprecated (Encaya does not replace it). We did do some work with certinject in this issue that is agnostic between positive and negative overrides, and some work that refactored existing positive override code in certinject; that was mainly because (1) we weren't yet sure if Encaya would work; (2) we knew that certinject would be needed for negative overrides anyway; and (3) positive overrides are easier to test in the certinject code than negative overrides, so having a good test suite for the positive override code in certinject reduces the risk of us introducing bugs in the negative override certinject code. Hope that makes sense.

@domob1812
Copy link
Collaborator

Ok, that makes perfect sense. Thanks for the clarification!

@JeremyRand
Copy link
Member Author

JeremyRand commented Feb 17, 2021

@domob1812 Week 5 has been completed. This consisted of setting up both Encaya certificate support and compressed ECDSA pubkey support in the following repos:

  • generate_nmc_cert
  • ncdns
  • safetlsa
  • certdehydrate_dane_rest_api (now renamed to encaya)

Encaya certificates with compressed ECDSA pubkeys now appear to work without issues on Windows, except that the Windows NSIS installer hasn't been updated to handle this yet (so manual installation is needed). I would expect this code to work in its current state with Chromium and Safari on macOS and GNU/Linux, but I haven't tested that.

Meanwhile, I also found a bug in the hlandau/service library that is breaking Windows Service support on Windows 10 (Windows 7 is unaffected). This is not strictly speaking a Namecoin bug, but since Hugo is a Namecoin developer and is also the maintainer of the library, and it's causing problems with ncdns (the Windows installer configures ncdns to run as a service), it's worth fixing. I spent some time debugging this (enough that I was able to trace it to Hugo's library, though I haven't fixed it yet).

In the process of debugging the service bug, I needed to see debug output from ncdns as a Windows Service, so I added Windows event logging to Hugo's dexlogconfig library, which ncdns uses. So now ncdns can log to the Windows event log, which will make future bug-squishing a lot easier.

I also refactored some TLSA code (in particular, we now use wildcard domains for TLSA records, which is more consistent with the RFC's, which don't allow name constraints to specify a specific protocol or port like DANE does). And I refactored some of the generate_nmc_cert code so that it saves the JSON to a file using the Golang JSON serializer instead of printing a manually generated JSON to the log. Also rebased generate_nmc_cert onto a current Go release, which gave us Ed25519 certs for free (although so far only OpenSSL and Go support Ed25519 in TLS, so it's not going to be useful in mainstream browsers yet).

EDIT: Forgot to mention, I also found and fixed a caching bug in ncdns (seems to have been there for years) that caused non-dehydrated TLSA records to be broken when returned by the cache instead of namecoind. I think this was also affecting DS records. Apparently almost no one uses DS or non-dehydrated TLSA records yet, so no one had reported this. Encaya certs are non-dehydrated, so it was important to fix here.

@domob1812 Is it okay to pay out for Week 5?

If funding Week 6 is approved, I plan to work on the following:

  • Windows NSIS installer support for Encaya.
  • Finish debugging the Windows Service bug, and get that fixed.
  • Release new ncdns Windows installer binaries that include Encaya and the Windows Service fix.

If that's finished ahead of schedule, I would probably look at testing Encaya on GNU/Linux and macOS.

@domob1812 Can we allocate Handshake funds for Week 6?

@domob1812
Copy link
Collaborator

ACK to payout for week 5.

For continuing the work here: This has already been going on much longer than originally planned, although of course it also includes a lot of deliverables (so that is not something bad). However, I think we should at some point start to get a comprehensive overview of what the final amount of work / cost will be, and when this will be entirely completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants