Summary

  • wolfSSL 5.9.2 disclosed a high-severity flaw in RPK-enabled builds: an unnegotiated Raw Public Key could be accepted in place of X.509 and bypass chain validation. The fix made X.509 the expected default and rejected any received form that differed from the negotiated form.
  • RFC 7250 and TLS 1.3 define Raw Public Key as a legitimate, explicitly negotiated certificate type carrying one DER SubjectPublicKeyInfo. The handshake can prove possession of its private key, but the bare SPKI carries no issuer-signed subject binding, validity interval, serial number or certificate extensions.
  • Safe RPK authority needs two independent proofs: runtime evidence that the correct certificate type was negotiated, and a fresh external binding that maps the exact SPKI to the intended host, service, device or role. A successful connection or transaction proves neither by itself.

A valid key entered through the wrong door

wolfSSL's 5.9.2 release described CVE-2026-55960 in unusually direct terms. In builds compiled with Raw Public Key support, a peer could present an RPK even though that form had not been negotiated. The library accepted it in place of an X.509 certificate. Because an RPK contains no certificate chain, the parse path did not perform the trust verification that the expected X.509 path required.

The affected feature was disabled by default in a standalone build, though included by --enable-all. The disclosure does not supply an exploitation count or a complete affected-version interval, so neither should be invented. What it does establish is the authority failure: receipt of one legitimate credential form was allowed to switch off the validation rules attached to another.

The repair defaulted the expected type to X.509 when no alternative had been negotiated. It compared the certificate form received from the server with the form selected by the client, and performed the corresponding check for client authentication on the server. A mismatch, including an unnegotiated RPK, now leads to UNSUPPORTED_CERTIFICATE. The linked pull request records regression tests for both directions.

This was not merely stricter parsing. The parser was never entitled to choose the trust model from the object it found. Certificate-type negotiation had already made that decision. The patch restored the ordering: agree on the validation contract, then accept only the credential form that contract permits.

Raw Public Key is a credential type, not a damaged certificate

RFC 7250 defines two extensions, client_certificate_type and server_certificate_type, and registers Raw Public Key as CertificateType value 2. A peer advertises the forms it can supply or process; the other side selects a common form. No new ciphersuite is needed simply because the certificate container changes.

When RPK is selected, the Certificate message carries the DER encoding of one SubjectPublicKeyInfo. That structure identifies the public-key algorithm, any algorithm parameters and the public-key bits. It is the same SPKI structure normally embedded inside an X.509 certificate, but the rest of the certificate is absent.

TLS 1.3 did not erase the design. RFC 8446 includes RawPublicKey(2) in CertificateType. If it was negotiated, the certificate list contains no more than one entry holding the RFC 7250 SPKI. The same standard states the default in operational language: the certificate type is X.509v3 unless another type is explicitly negotiated.

That distinction prevents two opposite mistakes. An RPK is not malformed X.509 and should not be rejected merely because it lacks a chain when RPK was selected. But a syntactically valid SPKI must not be accepted as a substitute for X.509 when the negotiation selected no such exception. Correctness depends on the pair (negotiated type, received form), not on whether either object can be parsed in isolation.

The signature proves a private key, not a machine name

TLS 1.3's CertificateVerify step can show that the peer holds the private key corresponding to the public key it supplied. The transcript binds that proof to the handshake. Finished then confirms the handshake state. These are important cryptographic facts.

They are not an identity directory.

RFC 5280 makes the omitted layer visible. A CA signature certifies the binding between public-key material and the certificate subject. The signed certificate body also carries issuer and subject names, a serial number, a validity interval and, in version 3, extensions that can constrain names, key usage, policy and other semantics. A relying party still has to build and validate a path and apply its own identity policy; X.509 is not self-executing authority. But it transports signed statements that a bare SPKI deliberately does not.

RFC 7250 therefore says its mechanism authenticates only when an out-of-band method binds the public key to the presenting entity. For both client and server authentication, the received SPKI must be authenticated by that external method. The implementation must also check the status of the binding.

The last sentence is the operational center of the design. A fingerprint copied during manufacturing may once have named sensor A. A TLSA record may once have associated a service name with key K. A TOFU database may once have accepted a first observation. None of those historical events proves that the binding is current after rotation, compromise, reassignment or retirement.

The missing certificate becomes an external ledger

An RPK deployment needs a record whose shape is often hidden behind the phrase “preconfigured key.” At minimum, it must say which canonical identity and role the SPKI names; the host, service or peer scope in which that name is valid; the exact DER SPKI or fingerprint; who authorized the binding; when it became effective; when it expires, if ever; how it is replaced; and what evidence proves the predecessor is no longer accepted.

The lookup key matters. A public key associated with gateway.example is not automatically authorized for every port, tenant or application role on that machine. A device key provisioned for telemetry is not a firmware-signing key. The same mathematical key can appear in several systems, but each authority relationship needs its own scope and owner.

GnuTLS exposes the boundary concretely. Its stored-key verification API looks up a public key by host and service, distinguishes “no entry” from “entry exists but key differs,” and can attach an expiry or use a custom backend. Its documentation also warns that ordinary certificate verification cannot authenticate an RPK because no certificate body exists; an out-of-band comparison or TOFU-style mechanism must be used.

Those APIs do not solve commissioning. They reveal what running code needs in order to make a decision. Someone must still populate the store, protect the update path, define the first-contact rule, own expiration and decide which application privilege a successful match unlocks.

wolfSSL makes the same responsibility explicit through a different interface. Applications enable RPK, configure certificate-type preferences and supply a verification callback to authenticate the received key outside TLS. Its TLS 1.3 interoperability example with GnuTLS completes the connection but reports the peer as not verified until that application logic exists. Protocol interoperability and peer identity are separate milestones.

DANE moves authority to DNSSEC—and to its operational clocks

RFC 7250 names DANE as one possible external binding. A TLSA record can associate a DNS service with selected certificate material. RFC 6698 defines an SPKI selector and full-value or digest matching, while DNSSEC authenticates the record set. This can remove the need to carry an issuer chain as the source of the name/key association.

It does not remove distributed state. The relying client must obtain a usable TLSA record, validate DNSSEC, interpret certificate usage, selector and matching type, and compare the right object. A published record that no client checks has administrative existence but no acceptance authority.

Rotation makes the clocks visible. RFC 7671 recommends pre-publishing the new association, waiting for stale DNS caches to expire, deploying the corresponding key or certificate and only then removing obsolete associations. During that interval, several valid views of the record set may coexist. The operator needs to know which verifiers can see which generation and whether both keys are intentionally accepted.

Firmware provisioning has the same problem with slower clocks. RFC 7925 describes constrained devices receiving peer keys or their hashes before communication and treats RPK as a middle ground between shared secrets and certificate infrastructure. Such devices may live for a decade. Their trust database changes at manufacturing, enrollment or software-update speed, not at TLS-handshake speed. Smaller messages transfer lifecycle work from the wire to the update authority; they do not make it disappear.

Seven facts must survive one green connection

A defensible event record separates at least seven observations.

First, configuration: which certificate types was this endpoint allowed to offer or accept, in which order and for which role? Second, negotiation: what did ClientHello offer and what did the peer select? Third, form: did the received bytes actually encode X.509 or one SPKI? Fourth, cryptography: did CertificateVerify and Finished succeed with the corresponding private key and transcript?

Fifth, identity: which external binding source mapped that SPKI to this host, service, device or role, at what version and freshness? Sixth, authority: which application permission did the mapping allow? Seventh, outcome: what traffic or operation was ultimately accepted?

Combining the seven into tls_success=true destroys the evidence needed to diagnose a type confusion. A successful transaction could follow an unnegotiated RPK, a stale but matching key, an external callback that never ran or an application privilege broader than the recorded role. Conversely, an unsupported_certificate refusal can be exactly the safe result even when the presented SPKI is well formed and controlled by its sender.

Heng Lu's running-code doctrine is useful here in a bounded sense. RFC text assigns semantics; IANA assigns extension numbers; a configuration expresses intent; an external record publishes a binding. None executes the final acceptance. Authority becomes operative where the live endpoint enforces the negotiated type, checks the current binding and applies a bounded application decision. The 2026 repair matters because it changed that executing veto.

Evidence limits

The source record supports a high-severity wolfSSL defect, its limited build scope and the repaired type check. It does not show that the issue was exploited, how many deployments enabled RPK or which earlier release first contained the behavior. The article therefore makes no exposure estimate.

Nor does the case show that RPK is inherently weaker than X.509. Correctly negotiated RPK with a protected, current external binding can be appropriate for constrained or closely provisioned systems. X.509 can fail through broken path validation, stale status, name-policy errors or misplaced application trust. The lesson is not to rank the formats. It is to prevent one format from inheriting the other's acceptance while escaping its validation rules.

Sources