python / python/cpython

SSLContext.load_verify_locations(cadata=<DER>) fails with [ASN1: NOT_ENOUGH_DATA] when linked against OpenSSL 3.0.21+

未關閉
#151,504 16 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

3.11 extension-modules topic-SSL type-bug
主要語言
Python
星號
77.2k
分支
36k
PR 合併指標
PR 指標待擷取

描述

Bug report

Bug description:

When CPython is linked against OpenSSL 3.0.21 (and likely any release carrying the CVE-2026-34180 ASN.1 hardening), SSLContext.load_verify_locations(cadata=) raises:

ssl.SSLError: [ASN1: NOT_ENOUGH_DATA] not enough data (_ssl.c:NNNN)

even for a single, perfectly valid DER certificate. On Windows this breaks ssl.create_default_context() outright, because SSLContext._load_windows_store_certs() loads the system trust store via cadata=. The practical effect is that all default-context HTTPS fails (e.g. importing aiohttp, which builds a default context at import time, crashes).

Reproducer (platform-independent)

import ssl
pem = ssl.get_server_certificate(("www.python.org", 443))
der = ssl.PEM_cert_to_DER_cert(pem)

ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.load_verify_locations(cadata=der)   # raises [ASN1: NOT_ENOUGH_DATA] on OpenSSL 3.0.21+
print("loaded OK")

OpenSSL 3.0.15 (and earlier): prints loaded OK.
OpenSSL 3.0.21: raises ssl.SSLError: [ASN1: NOT_ENOUGH_DATA].

The certificate itself is fine — calling d2i_X509 directly against the same libcrypto-3.dll parses it successfully; only the path through _ssl fails.

Root cause
In Modules/_ssl.c, _add_ca_certs() reads certs in a loop until d2i_X509_bio() returns NULL, then inspects the leftover error to distinguish a clean end-of-buffer from a real failure. It only accepts ASN1_R_HEADER_TOO_LONG as the benign EOF marker:

} else if ((filetype == SSL_FILETYPE_ASN1) &&
                (ERR_GET_LIB(err) == ERR_LIB_ASN1) &&
                (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG)) {
    /* EOF ASN1 file, not an error */
    ERR_clear_error();
    retval = 0;
}

OpenSSL 3.0.21 now reports end-of-buffer as ASN1_R_NOT_ENOUGH_DATA (reason 142) instead of ASN1_R_HEADER_TOO_LONG. That reason isn't whitelisted, so the function falls through to the generic error branch and raises, discarding the load. Confirmed by reading ERR_peek_last_error() after the final d2i_X509_bio() on a single-cert buffer: 0x0680008E = asn1 ... not enough data.

Proposed fix
Treat ASN1_R_NOT_ENOUGH_DATA as a clean EOF alongside ASN1_R_HEADER_TOO_LONG:

} else if ((filetype == SSL_FILETYPE_ASN1) &&
                (ERR_GET_LIB(err) == ERR_LIB_ASN1) &&
                ((ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG) ||
                 (ERR_GET_REASON(err) == ASN1_R_NOT_ENOUGH_DATA))) {
    /* EOF ASN1 buffer, not an error (OpenSSL 3.0.21+ reports the
       end-of-data condition as ASN1_R_NOT_ENOUGH_DATA). */
    ERR_clear_error();
    retval = 0;
}

With this change, load_verify_locations(cadata=...) succeeds, the Windows store loads fully, and TLS verification works again.

Environment
CPython 3.11.15 (self-built, Windows x64, MSVC), linked against self-compiled OpenSSL 3.0.21.
Windows 11.
Also expected to affect any build/version of CPython linked against OpenSSL ≥ 3.0.21 (or whichever release introduced the reason-code change), on any platform, for the DER cadata path.

CPython versions tested on:

3.11

Operating systems tested on:

Windows

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

研究方向

從 Modules/_ssl.c 中的 _add_ca_certs() 開始,特別檢查 d2i_X509_bio() 迴圈以及對 ERR_peek_last_error() 的處理。使用提供的 ssl 範例重現 DER cadata 失敗,然後驗證單一憑證能夠成功載入,並確認在更新後的 EOF 處理下,Windows 預設內容的信任儲存區載入能夠正常運作。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
python
領域
security
Issue 類型
缺陷
難度
3/5
預估耗時
1-2 天
活躍度
活躍
描述清晰度
描述清楚
新手友好度
74/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。