From 3081a05cf704baf2fd6852e0c5981d6dce47fdfb Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Fri, 23 Oct 2026 13:56:38 +0300 Subject: [PATCH] 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 --- src/ssllib.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/ssllib.c b/src/ssllib.c index 8e83999..db8f3be 100644 --- a/src/ssllib.c +++ b/src/ssllib.c @@ -22,6 +22,7 @@ #include #include #include +#include #else #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #endif #include "proxy.h" @@ -115,6 +117,31 @@ static int add_ext(X509 *cert, int nid, const char *value) } #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) { 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 */ 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_issuer_name(dst_cert, X509_get_subject_name(config->CA_cert))){ X509_free(dst_cert);