MITM: a serial number of its own when wolfSSL cannot copy the source's

wolfSSL built with WOLFSSL_QT, as Ubuntu 26.04's 5.9.1 is, returns a
serial number without the ASN.1 header its X509_set_serialNumber()
requires, so every certificate copy failed. The copy then gets a
positive serial number from the hash of the source certificate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Vladimir Dubrovin 2026-10-23 13:56:38 +03:00
parent e13c8d518f
commit 3081a05cf7

View File

@ -22,6 +22,7 @@
#include <wolfssl/openssl/pem.h> #include <wolfssl/openssl/pem.h>
#include <wolfssl/openssl/ssl.h> #include <wolfssl/openssl/ssl.h>
#include <wolfssl/openssl/err.h> #include <wolfssl/openssl/err.h>
#include <wolfssl/openssl/bn.h>
#else #else
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/x509.h> #include <openssl/x509.h>
@ -29,6 +30,7 @@
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/bn.h>
#endif #endif
#include "proxy.h" #include "proxy.h"
@ -115,6 +117,31 @@ static int add_ext(X509 *cert, int nid, const char *value)
} }
#endif #endif
/* A serial number of the copy's own, when the source's cannot be set back:
* positive, from the hash of the source certificate, so the same for the
* same certificate and different for another. wolfSSL built with
* WOLFSSL_QT, as Ubuntu 26.04 has it, returns a serial number without the
* ASN.1 header its own X509_set_serialNumber() requires.
*/
static int set_serial_hash(X509 *cert, const unsigned char *hash)
{
unsigned char serial[16];
BIGNUM *bn;
ASN1_INTEGER *ai;
int res = 0;
memcpy(serial, hash, sizeof(serial));
serial[0] &= 0x7f;
if(!serial[0]) serial[0] = 1;
if(!(bn = BN_bin2bn(serial, sizeof(serial), NULL))) return 0;
if((ai = BN_to_ASN1_INTEGER(bn, NULL))){
res = X509_set_serialNumber(cert, ai);
ASN1_INTEGER_free(ai);
}
BN_free(bn);
return res;
}
SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config) SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
{ {
int err = -1; int err = -1;
@ -162,7 +189,8 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
} }
/* v3 is required, extensions are added below */ /* v3 is required, extensions are added below */
X509_set_version(dst_cert, 2); X509_set_version(dst_cert, 2);
if(!X509_set_serialNumber(dst_cert, X509_get_serialNumber(src_cert)) if((!X509_set_serialNumber(dst_cert, X509_get_serialNumber(src_cert))
&& !set_serial_hash(dst_cert, hash_sha256))
|| !X509_set_subject_name(dst_cert, X509_get_subject_name(src_cert)) || !X509_set_subject_name(dst_cert, X509_get_subject_name(src_cert))
|| !X509_set_issuer_name(dst_cert, X509_get_subject_name(config->CA_cert))){ || !X509_set_issuer_name(dst_cert, X509_get_subject_name(config->CA_cert))){
X509_free(dst_cert); X509_free(dst_cert);