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.