LibreSSL项目中TLSv1.3握手时"unknown pkey type"错误的分析与解决

LibreSSL项目中TLSv1.3握手时"unknown pkey type"错误的分析与解决

portable LibreSSL Portable itself. This includes the build scaffold and compatibility layer that builds portable LibreSSL from the OpenBSD source code. Pull requests or patches sent to tech@openbsd.org are welcome. portable 项目地址: https://gitcode.com/gh_mirrors/po/portable

在LibreSSL项目中,当服务器配置了多个证书(如ECDSA和RSA证书)并尝试通过限制支持的签名算法来强制使用特定证书时,可能会遇到一个奇怪的问题。这个问题会导致TLSv1.3握手过程中出现"unknown pkey type"错误,即使握手最终成功完成。

问题现象

在测试环境中,当使用LibreSSL 3.9.2版本时,系统日志中会出现两种类型的错误信息:

  1. 握手失败情况下的关键错误:
SSL_do_handshake() failed (SSL: error:1402D0FB:SSL routines:ACCEPT_SW_CERT:unknown pkey type)
  1. 握手成功但仍报告的错误:
ignoring stale global SSL error (SSL: error:1402D0FB:SSL routines:ACCEPT_SW_CERT:unknown pkey type)

这些错误看起来与密钥类型有关,但实际上不应该发生,特别是在握手成功的情况下。

问题根源分析

经过深入分析,发现问题出在LibreSSL的TLSv1.3实现中,具体涉及以下几个关键函数:

  1. ssl_sigalg_select()函数:这个函数负责根据客户端支持的签名算法选择适当的证书。当找不到匹配的签名算法时,它会向错误队列中添加一个SSL_R_UNKNOWN_PKEY_TYPE错误。

  2. tls13_server_check_certificate()函数:在TLSv1.3握手过程中,服务器会调用此函数来检查每个证书是否可用。

  3. tls13_server_select_certificate()函数:这个函数会依次尝试ECDSA和RSA证书。即使ECDSA证书因客户端不支持相应签名算法而无法使用,函数仍会继续尝试RSA证书。

问题的关键在于:当检查ECDSA证书失败时,ssl_sigalg_select()会将错误添加到错误队列中,但后续成功使用RSA证书后,这个错误仍然留在错误队列中未被清除。这导致了两种不良后果:

  • 如果SSL_do_handshake()阻塞,错误会被SSL_get_error()报告,导致握手失败
  • 如果SSL_do_handshake()立即完成,错误会留在队列中,稍后被当作"stale error"报告

解决方案

这个问题已经在LibreSSL 4.0.0版本中得到修复。修复的核心思路是正确处理错误队列中的SSL_R_UNKNOWN_PKEY_TYPE错误,确保在证书选择过程中产生的临时错误不会影响最终的握手结果。

对于仍在使用旧版本的用户,一个临时解决方案是在SSL_do_handshake()之后检测并清除SSL_R_UNKNOWN_PKEY_TYPE错误。这可以避免错误被误报,但建议用户尽快升级到4.0.0或更高版本以获得完整的修复。

技术影响

这个问题虽然不会在所有配置下出现,但对于需要支持多种证书类型(如同时支持ECDSA和RSA)的服务器来说尤为重要。特别是在以下场景中影响较大:

  1. 需要根据客户端能力动态选择证书类型的场景
  2. 使用较新加密算法(如ECDSA)但需要兼容只支持传统算法(如RSA)的老客户端
  3. 需要严格控制可用签名算法以提高安全性的环境

最佳实践建议

为了避免类似问题,建议TLS服务器管理员:

  1. 保持LibreSSL更新到最新稳定版本
  2. 在配置多个证书时,确保测试各种客户端连接场景
  3. 监控服务器日志中的SSL错误,特别是看似不合理的错误报告
  4. 在升级前,在测试环境中验证新版本的行为

通过理解这个问题的本质和解决方案,系统管理员可以更好地维护TLS服务的稳定性和安全性。

portable LibreSSL Portable itself. This includes the build scaffold and compatibility layer that builds portable LibreSSL from the OpenBSD source code. Pull requests or patches sent to tech@openbsd.org are welcome. portable 项目地址: https://gitcode.com/gh_mirrors/po/portable

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凤田峥Amanda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值