With the help of CCP's security expert, we noticed that the sites that were failing had certificate chains up to a root certificate with a very strong signature algorithm, ecdsa-with-SHA384, and chances were that Wine did not support that particular algorithm.
Now what?Personally I'm no expert in security algorithms, SSL or TSL or anything like that, so I wasn't sure where to even begin looking at Wine source code to see if this algorithm was supported.
After some digging around I decided to look at the output of the secur32 channel:
Then I started up the EVE client and opened up the browser, entering https://zkillboard.com in the address bar. There was quite a lot of output - no errors or warnings, though, and no smoking gun to be found. The functions in secur32 are very low level, though, and I found they were being called from functions in crypt32. Adding the crypt channel to the debug output would in theory give a clearer view of what was going on, but now I had the problem that the log was up to 800k lines.
I disabled the code that gets the root certificates from the system and pointed it to a bundle read from disk - I could then trim that bundle to only include the root certificate used by this particular site - Comodo ECC. This resulted in a log of around 10k lines - somewhat more manageable. Now I was able to confirm that this root certificate did not import properly due to a bad signature. Adding a bit more detailed logging confirmed that the bad signature stemmed from signature algorithm not being recognized.
But it works on LinuxI spent a bit of time trying to figure out what would be needed to add support for this signature algorithm - ecdsa-with-SHA384, but after a day or so realized that this was a rabbit hole I probably shouldn't be going down. I also found out that this troublesome site seemed to work fine on Linux. Feeling stupid for not checking that sooner, I compiled Wine on my Ubuntu box from the same repo and tested this. Sure enough, https://zkillboard.com loaded up just fine in the ingame browser.
Well, great, I thought, I can use the implementation for Linux as a reference to get this to work on OS X. When looking through the code I quickly found that there was no support for this algorithm, or any ECC certificates on Linux either. Pouring over the logs from Linux also revealed that this same root certificate failed to import, so there had to be some other way for that site to get certified.
Consider the alternativesWe took another look at zkillboard.com and found that there was an alternate chain, with a root certificate with a more typical RSA type signature. The question still remained, though - why did Wine on OS X not validate the alternate certificate chain when Wine on Linux did?
I added the Comodo RSA root certificate to the bundle I was using on the Mac, and it imported fine. Still the site wouldn't work. I figured there had to be some issue with finding that alternate chain, but as I knew very little about SSL in general this was a bit of a needle in a haystack situation. Being stubborn I figured I had no other option than digging into the Wine source, trying to understand what was going on.
I started tracing through CertGetCertificateChain in dlls/crypt32/chain.c, trying to understand how that worked and why it wouldn't accept the alternate chain we knew was available for this site. After adding more detailed logging I was convinced that this code was simply not getting an alternate chain. Why did this work on Linux, then?
The smoking gunI went back to the Linux machine, ran the EVE client with the secur32 and crypt channels enabled and started analyzing the logs. Finally I noticed that the handshake was logged in some detail.
trace:secur32:schan_gnutls_log <4> HSK[0x7d416a18]: SERVER KEY EXCHANGE (12) was received. Length 327, frag offset 0, frag length: 327, sequence: 0
trace:secur32:schan_gnutls_log <4> HSK[0x7d416a18]: Selected ECC curve SECP256R1 (2)
trace:secur32:schan_gnutls_log <4> HSK[0x7d416a18]: CLIENT KEY EXCHANGE was queued [70 bytes]
trace:secur32:schan_gnutls_log <4> REC[0x7d416a18]: Sent ChangeCipherSpec
trace:secur32:schan_gnutls_log <4> HSK[0x7d416a18]: Cipher Suite: ECDHE_RSA_AES_128_CBC_SHA1
Maybe this would have been obvious to somebody that knows SSL well, but I hadn't realized that the server decides what certificate chain to send to the client. I guess it sends the strongest chain it has, unless the client specifically asks for a weaker cipher. I finally felt I was getting somewhere - now I just had to figure out how do the same on the Mac.
A secure session starts in InitializeSecurityContext, which is implemented in dlls/secur32/schannel.c. It calls schan_imp_create_session, which is in dlls/secur32/schannel_macosx.c - that function uses functions provided from OS X - SSLNewContext, for example, then later on SSLHandshake is called. I got a bit worried that since OS X handled the handshake I wouldn't be able to affect it, but a bit of searching led me to SSLSetEnabledCiphers.