SChannel中的密码套件选择



我已经实现了(Windows 10.0.17763.0/VS2017/C++)一个客户端/服务器应用程序,该应用程序使用schannel进行安全通信。现在的要求是只使用一组密码套件来进行某些客户端和服务器之间的通信。

使用BCryptAddContextFunction/BCryptRemoveContextFunction API,我可以更改SChannel中支持的密码,但这是一个系统范围的设置,而不仅仅适用于我的应用程序。为了以编程方式控制它,我尝试使用AcquireCredentialsHandle中的ALG_ID。以下是我的应用程序应该支持的唯一密码套件。

  • 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

所以我构造了如下ALG_ID。

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];

使用wireshark,我发现以下是我的应用程序在客户端hello中使用上述ALG_ID、提出的密码套件

  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_cdsa_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_cdsa_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

问题是,

  1. 如何只允许AES_GCM批量加密?当我将CALG_AES添加到列表中时,AES_GCM和AES_CBC都被允许
  2. 如何控制签名?添加CALG_ECDH_EPHEM启用了TLS_ECDHE_ECDSA以及TLS_ECDCHE_RSA,其中我只需要TLS_ECDHE_RSA。向ALG_ID添加CALG_RSA_SIGN删除了TLS_ECDHE_ECDSA,但它开始允许TLS_RSA_*密码套件

在调用AcquireCredentialsHandle函数时,可以使用SCH_CREDENTIALS结构而不是SCHANNEL_CRED。

使用CRYPTO_SETTINGS结构的数组创建TLS_PARAMETERS。每个CRYPTO_SETTINGS结构都定义了密钥交换、签名、摘要和批量密码算法的限制。然后,您可以选择满足您的应用程序要求的组合。此结构(SCH_CREDENTIALS)使用SCHANNEL_USE_BLACKLIST标志/方法,禁用指定TLS会话不需要的内容。通过CRYPTO_SETTINGS结构的eAlgorithUsage和strCngAlgId成员的正确组合,我认为您可以实现TLS会话所需的行为。

请参阅https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-sch_credentials

https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-tls_parameters

例如,如果将AES_CBC包含在其中一个具有适当eAlgorithUsage成员值的限制中,在本例中为TlsParametersCngAlgUsageCipher,则应将其作为批量加密算法从会话中排除。请确保使用该eAlgorithUsage将AES_GCM排除在限制之外。

关于控制签名算法,值为TlsParametersCngAlgUsageSignature的CRYPTO_SETTINGS结构eAlgorithUsage成员限制使用分配给strCngAlgId成员的算法作为该会话的签名算法。您还可以确定要限制的最小和最大长度。

最后,

"Protocols项下注册表项中的DisabledByDefault值不优先于包含SCHANNEL凭据数据的SCHANNEL_CRED结构中定义的grpitEnabledProtocols值"(https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/restrict-cryptographic-algorithms-protocols-schannel)。

对于该TLS会话的TLS_PARAMETER结构的grbitDisabledProtocols成员也是如此。

如果您对签名算法、密钥交换、批量加密和摘要的限制进行了正确的组合,则可以在密码套件中的特定位置过滤出不需要的算法。

使用CNG函数:此处的示例https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/SecAuthN/prioritizing-schannel-cipher-suites.md

此外;协商密码套件时,客户端会发送一条包含密码套件列表的握手消息它会接受的。服务器从列表中进行选择,并发回一条握手消息,指示它将接受哪个密码套件。尽管客户端可能会根据其认为首先列出的最强密码套件对列表进行排序,但服务器可能会忽略首选顺序并选择客户端提出的任何密码套件。服务器可能有自己的密码套件偏好顺序,并且可能与客户端不同。因此,不能保证谈判会达成最强有力的共同套件。如果没有通用的密码套件客户端和服务器,连接被中止"-

NIST特别出版物800-52修订版2运输选择、配置和使用指南层安全(TLS)实现,第3.3.1节密码套件。Kerry A.McKayDavid A.Cooper计算机安全处信息技术实验室本出版物可从以下网站免费获取:https://doi.org/10.6028/NIST.SP.800-52r2

最新更新