net_socket_ssl_bear: decode PEM bodies by their compacted length

delete_linebreaks() compacts the certificate body in place but never
terminated the compacted run, and the caller kept passing the span of
the original line-wrapped body to unbase64(). Since unbase64() now
insists on an exact 4-aligned length, every wrapped PEM certificate
was rejected and the BearSSL trust store ended up empty; before that
guard the stale tail bytes decoded as garbage instead. Strip CR as
well as LF, NUL-terminate the compacted run, hand unbase64() its
strlen(), and skip certificates it refuses rather than pushing a
NULL blob into the X.509 decoder.

Also stop scanning when a BEGIN marker has no matching END marker so
a truncated bundle cannot drive strstr() past the buffer.
This commit is contained in:
libretroadmin committed 2026-08-22 05:34:49 +02:00
1 parent 8766e7e473
commit 3a253df478
1 file changed
+23 -12
+23 -12
View File
@@ -166,24 +166,26 @@ static bool append_cert_x509(void* x509, size_t len)
return true;
}
/* Compacts a PEM body in place, dropping every CR and LF, and
* NUL-terminates the compacted run so strlen() yields the exact
* number of base64 characters. The input is not needed by the
* caller afterwards, so in-place rewriting is fine. */
static char* delete_linebreaks(char* in)
{
char* iter_in;
char* iter_out;
while (*in == '\n')
while (*in == '\n' || *in == '\r')
in++;
iter_in = in;
while (*iter_in != '\n' && *iter_in != '\0')
iter_in++;
iter_out = iter_in;
iter_in = in;
iter_out = in;
while (*iter_in != '\0')
{
while (*iter_in == '\n')
iter_in++;
*iter_out++ = *iter_in++;
if (*iter_in != '\n' && *iter_in != '\r')
*iter_out++ = *iter_in;
iter_in++;
}
*iter_out = '\0';
return in;
}
@@ -204,13 +206,22 @@ static void append_certs_pem_x509(char * certs_pem)
break;
cert += STRLEN_CONST("-----BEGIN CERTIFICATE-----");
cert_end = strstr(cert, "-----END CERTIFICATE-----");
if (!cert_end)
break;
*cert_end = '\0';
cert = delete_linebreaks(cert);
cert_bin = unbase64(cert, cert_end-cert, &cert_bin_len);
append_cert_x509(cert_bin, cert_bin_len);
free(cert_bin);
/* unbase64() requires an exact, 4-aligned length. The compacted
* run is shorter than (cert_end - cert) by the number of line
* breaks removed, so measure it rather than reusing the span of
* the original wrapped body. */
cert_bin = unbase64(cert, (int)strlen(cert), &cert_bin_len);
if (cert_bin)
{
append_cert_x509(cert_bin, cert_bin_len);
free(cert_bin);
}
cert_end++; /* skip the NUL we just added */
}