I have implemented (Windows 10.0.17763.0/VS2017/C++) a client/server app which does secure communication using schannel. Now the requirement is to use only a set of cipher suites for the communication between certain clients and servers.
Using BCryptAddContextFunction/BCryptRemoveContextFunction APIs i can change the supported ciphers in SChannel but that is a system wide setting and not just for my application. In order to control it programmatically, i tried using the ALG_IDs in AcquireCredentialsHandle. Below are the only cipher suites my app is supposed to support.
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
So i constructed the ALG_IDs like below.
std::vector<ALG_ID> algos = { CALG_AES_256 , CALG_AES_128 , CALG_SHA_384 , CALG_SHA_256,CALG_ECDH_EPHEM,CALG_DH_EPHEM };
schannelCred.cSupportedAlgs = static_cast<DWORD>(algos.size());
schannelCred.palgSupportedAlgs = &algos[0];
Using wireshark i figured that below are the cipher suites my app is proposing in the client hello using the above ALG_IDs,
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
The problem is,
- How do i allow only AES_GCM bulk encryption ? when i add CALG_AES to the list, both AES_GCM and AES_CBC are getting allowed.
- How do i control the signature ? Adding CALG_ECDH_EPHEM enabled both TLS_ECDHE_ECDSA as well as TLS_ECDHE_RSA where i need only TLS_ECDHE_RSA. adding CALG_RSA_SIGN to the ALG_ID removed TLS_ECDHE_ECDSA but it stared allowing TLS_RSA_* cipher suites.
Use CNG functions: Examples here https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/SecAuthN/prioritizing-schannel-cipher-suites.md
Also, "When negotiating a cipher suite, the client sends a handshake message with a list of cipher suites it will accept. The server chooses from the list and sends a handshake message back indicating which cipher suite it will accept. Although the client may order the list with what it considers to be the strongest cipher suites listed first, the server may ignore the preference order and choose any of the cipher suites proposed by the client. The server may have its own cipher suite preference order, and it may be different from the client’s. Therefore, there is no guarantee that the negotiation will settle on the strongest common suite. If no cipher suites are common to the client and server, the connection is aborted." -
NIST Special Publication 800-52 Revision 2 Guidelines for the Selection, Configuration, and Use of Transport Layer Security (TLS) Implementations, Section 3.3.1 Cipher Suites. Kerry A. McKay David A. Cooper Computer Security Division Information Technology Laboratory This publication is available free of charge from: https://doi.org/10.6028/NIST.SP.800-52r2