openssl: X509_cmp fails since 1.1.1f

Our internal comparison of X509 certificate is broken since 1.1.1f. If you run this example with 1.1.1e you get “works”. If you run the same with 1.1.1f or higher you get “broken”.

It creates two X509* pointer from same pem. They should be equal.

#include <cstring>
#include <iostream>
#include <openssl/x509.h>

static const char b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static const char reverse_table[128] = {
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
	64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
	64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64
};


::std::string base64_decode(const ::std::string& ascdata)
{
	using ::std::string;
	string retval;
	const string::const_iterator last = ascdata.end();
	int bits_collected = 0;
	unsigned int accumulator = 0;

	for (string::const_iterator i = ascdata.begin(); i != last; ++i)
	{
		const int c = *i;
		if (::std::isspace(c) || c == '=')
		{
			// Skip whitespace and padding. Be liberal in what you accept.
			continue;
		}
		if ((c > 127) || (c < 0) || (reverse_table[c] > 63))
		{
			throw ::std::invalid_argument("This contains characters not legal in a base64 encoded string.");
		}
		accumulator = (accumulator << 6) | reverse_table[c];
		bits_collected += 6;
		if (bits_collected >= 8)
		{
			bits_collected -= 8;
			retval += static_cast<char>((accumulator >> bits_collected) & 0xffu);
		}
	}
	return retval;
}


X509* get_x509(const std::string pem)
{
	std::string decoded = base64_decode(pem);

	X509* x = nullptr;
	unsigned char* buf = nullptr;
	const unsigned char* p = (const unsigned char*) decoded.c_str();
	int len = decoded.size();

	if (d2i_X509(&x, &p, len) == NULL)
	{
		std::cout << "mistake" << std::endl;
	}

	return x;
}


int main()
{
	const std::string pem("MIIDJTCCAg2gAwIBAgIUEUSW5o7qpgNCWyXic9Fc9tCLS0gwDQYJKoZIhvcNAQELBQAwEzERMA8GA1UEAwwIUGVyc29TaW0wHhcNMjAxMjE2MDY1NjM5WhcNMzAxMjE2MDY1NjM5WjATMREwDwYDVQQDDAhQZXJzb1NpbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMsgRKnnZbQtG9bB9Hn+CoOOsanmnRELSlGq521qi/eBgs2wSdHYM6rsJFwY89RvINLGeUZh/pu7c+ODtTafAWE3JkynG01d2Zrvp1V1r97+FGyDf+b1hAggxBy70bTRyr1gAoKQTAm74U/1lj13EpWz7zshgXJ/Pn/hUyTmpNW+fTRExaifN0jkl5tZUURGA6w3+BRhVDQtt92vLihqUGaEFpL8yqqFnN44AoQ5+lgMafWiUyYMHcK75ZB8WWklq8zjRP3xC1h56k01rT6KJO6i+BxMcADerYsn5qTlcUiKcpRUb6RzLvCUwj91t1aX6npDI3BzSP+wBUUANBfuHEMCAwEAAaNxMG8wFwYDVR0OBBA8yBBnvz1Zt6pHm2GwBaRyMBcGA1UdIwQQPMgQZ789WbeqR5thsAWkcjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAIEzVbttOUc7kK4aY+74TANFZK/qtBQ794a/P30TGWSRUq2HnDsR8Vo4z8xm5oKeC+SIi6NGzviWYquuzpJ7idcbr0MIuSyD+Vg6n1sG64DxWNdGO9lR5c4mWFdIajShczS2+4QIRB/lFZCf7GhPMtIcbP1o9ckY2vyv5ZAEU9Z5n0PY+abrKsj0XyvJwdycEsUTywa36fuv6hP3UboLtvK6naXLMrTjWtSA6PXjHy7h8h0NC8XLk64mc0lcRC4WM+xJ/C+NHglpmBqBxnStpnZykMZYD1VyJJ1wNc+Y3e2uMBDxZviH3dIPIgqP1Vpi2TWfqr3DTBNCRf4dl/wwNU8=");

	X509* x1 = get_x509(pem);
	X509* x2 = get_x509(pem);

	if (X509_cmp(x1, x2) == 0)
	{
		std::cout << "works" << std::endl;
		X509_free(x1);
		X509_free(x2);
		return 0;
	}

	X509_free(x1);
	X509_free(x2);

	std::cout << "broken" << std::endl;
	return 1;
}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 17 (17 by maintainers)

Commits related to this issue

Most upvoted comments

It’s probably returning -2 to indicate an error.

This basically means the certificate is invalid.