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

SChannel/WinSSL: Implement public key pinning #1429

Closed

Conversation

moparisthebest
Copy link
Contributor

This implements public key pinning for the schannel backend. Currently it works with pem/der/hashes, but only if the remote server has a RSA key with a length of 2048 or 4096 bits. I'm looking for help with this error that occurs with ecDSA keys (regardless of PROV_RSA_FULL or PROV_RSA_AES):

moparisthebest@1d49e25#diff-2ba9d5898aad590d89cd83e17ad244fbR1658

And also hoping that I don't really have to resort to the horrible hard-coded header hacks that the apple backend had to do:

moparisthebest@1d49e25#diff-2ba9d5898aad590d89cd83e17ad244fbR1719

Is there a proper way to change a PUBLICKEYBLOB to a DER (or a PEM that I can convert)?

Also thoughts about this working on XP, 8, or 10 would be appreciated too, I've only tested on 7 SP1.

@mention-bot
Copy link

@moparisthebest, thanks for your PR! By analyzing the history of the files in this pull request, we identified @bagder, @yangtse and @mback2k to be potential reviewers.

@bagder bagder requested a review from mback2k April 19, 2017 13:44
@bagder
Copy link
Member

bagder commented Apr 19, 2017

Hey @mback2k, we could use your keen eyes and area expertise here...

@mback2k
Copy link
Member

mback2k commented Apr 21, 2017

Hey @bagder, I will try to take a look this weekend. I don't have much time at the moment and I am drowning in roughly 3000 GitHub notifications and 1000 mailinglist mails. If something like this comes up, could you please send me a direct message? Thanks. :-)

Copy link
Member

@mback2k mback2k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your hard work on this feature and pull-request, I really appreciate it. I hope that you will find the time to address my review comments, thanks!

@@ -1576,6 +1610,159 @@ CURLcode Curl_schannel_random(unsigned char *entropy, size_t length)
return CURLE_OK;
}

static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend the same as in #1325 (comment) and would like to see such a function moved to a separate source file, e.g. schannel_cert.c.

lib/vtls/schannel.c Outdated Show resolved Hide resolved
not sure what second arg should be,
X509_PUBLIC_KEY_INFO -- fails
RSA_CSP_PUBLICKEYBLOB -- not quite der, missing spki header bytes
CNG_RSA_PUBLIC_KEY_BLOB -- fails
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will take a look into this. You may also find some answers in my WinCNG-based implementation for libssh2. CNG is the successor of crypt32 and requires the use of the bcrypt library. See: https://github.com/libssh2/libssh2/blob/master/src/wincng.c

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will look thank you

lib/vtls/schannel.c Outdated Show resolved Hide resolved
lib/vtls/schannel.c Outdated Show resolved Hide resolved
@@ -1716,4 +1903,69 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
}
#endif /* _WIN32_WCE */

static void Curl_schannel_checksum(const unsigned char *input,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would advise to have a return value that tells the user of this function if the checksum failed or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it can't? It's used to define curlssl_sha256sum (and later curlssl_md5sum), and that function doesn't have a return value. schannel appears to be the only backend where it even has a possibility of failure, which might be why it wasn't implemented before...

@dscho
Copy link
Contributor

dscho commented Aug 28, 2017

@moparisthebest I see that this PR's changes conflict with my PR to configure TLS backends at runtime (which was just merged to master).

Would you like me to assist you in resolving the merge conflicts?

@moparisthebest
Copy link
Contributor Author

@dscho Thanks for the offer and that amazing runtime TLS switching work. I can probably handle the merge conflicts myself whenever I get around to spinning windows back up and cleaning this up to be merged.

I'm still unable to support anything but RSA keys with bit length of 2048 or 4096, but unless someone who knows what they are doing with schannel comes along, I'll probably just submit it as-is. It's better than nothing anyway. :)

@dscho
Copy link
Contributor

dscho commented Sep 1, 2017

I can probably handle the merge conflicts myself

Cool!

I'm still unable to support anything but RSA keys with bit length of 2048 or 4096

As you say, it is better than nothing! And if anybody comes along with the need for different sizes, then that will give them a perfect opportunity to "pay back" to the project ;-)

@moparisthebest moparisthebest changed the title WIP: SChannel/WinSSL: Implement public key pinning SChannel/WinSSL: Implement public key pinning Jan 16, 2018
@moparisthebest
Copy link
Contributor Author

In October @boris9000 (thanks!) put in a pull request to fix this patch to support all types of certificates and keys. I finally got another windows dev box spun up and was able to rebase my and his commit on top of master, including the new runtime TLS backend support.

I have tested it with rsa4096 and ecDSA Secp256r1 keys like so:

curl.exe https://www.moparisthebest.com --insecure --pinnedpubkey 'sha256//t62CeU2tQiqkexU74Gxa2eg7fRbEgoChTociMee9wno=' -s -S -o test.out.txt
curl.exe https://blog.joelj.org --insecure --pinnedpubkey 'sha256//1cCBZSdgsO2/rHuPlfHELChj+wCD2C7X5DnbefNoY0o=' -s -S -o test.out.txt

Additionally I added another not-really-needed commit to replace Curl_none_md5sum with Curl_schannel_md5sum, if this isn't desired I can pull it.

If @dscho wouldn't mind giving it a quick once-over to make sure I didn't do anything to harm the runtime TLS stuff, and @mback2k wouldn't mind making sure the windows specific code looks OK then I believe it is ready to merge.

Note: I have only tested this on Windows 7 SP1 x86, and don't really have the ability to run it on anything else.

@bagder
Copy link
Member

bagder commented Jan 25, 2018

thanks!

@bagder bagder closed this in e178fbd Jan 25, 2018
@lock lock bot locked as resolved and limited conversation to collaborators May 5, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants