Skip to content

ssl: certificate verification failures all report -9984; surface the mbedtls verify flags #11148

Description

@dhalbert

Note: this issue was written by Claude.

Every certificate verification failure in the ssl module surfaces as the same bare number, so there is no way to distinguish a hostname mismatch from an expired certificate, an untrusted CA, or a key-usage problem.

shared-module/ssl/SSLSocket.c never calls mbedtls_ssl_get_verify_result(). A failed handshake goes straight to mbedtls_raise_error(ret) (line 364) with ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED (-0x2700 = -9984), so the MBEDTLS_X509_BADCERT_* bitmask — which records exactly which check failed — is discarded.

This came up while debugging #10339, where the real cause was BADCERT_CN_MISMATCH arising from an unsupported iPAddress SAN. Identifying that required reading mbedtls source; the flag would have named it immediately.

CPython precedent: ssl.SSLCertVerificationError carries verify_code and verify_message, both included in str(e). The same condition there reads:

verify_code=62  verify_message="Hostname mismatch, certificate is not valid for 'nope.invalid'."

Two options, with a footprint tradeoff:

  1. Append the raw bitmask from mbedtls_ssl_get_verify_result() to the exception. Nearly free in flash, and adds no new translatable strings — the value is a number.
  2. Render it with mbedtls_x509_crt_verify_info(), which exists in lib/mbedtls 2.28 (include/mbedtls/x509_crt.h:561) and is not compiled out (MBEDTLS_X509_REMOVE_INFO is not defined in lib/mbedtls_config/mbedtls_config.h). Human-readable, but pulls in mbedtls's message strings, which is a real cost on small boards — and that text is untranslated English.

Claude has not attempted a patch; this is a report of the diagnostic gap.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions