mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Use explicit fetching of digests in channel binding (OpenSSL >= 3.0)
This commit touches both the libpq and backend-side code of channel binding where respectively pgtls_get_peer_certificate_hash() and be_tls_get_certificate_hash() are upgraded to retrieve digests using the method recommended by OpenSSL 3.0: no more direct EVP_sha256() or similar, just a EVP_MD_fetch() through EVP to get an algorythm type, based on a name. The pre-3.0 code is still required for LibreSSL and as long as we support OpenSSL 1.1.1. Similar work has been done inb91f79cd08and1f3b9bb109. Author: Mark Atwood <mark@reviewcommit.com> Co-authored-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/178596055149.1584250.13974609482797470185@reviewcommit.com
This commit is contained in:
@@ -2282,7 +2282,12 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
|
||||
{
|
||||
X509 *server_cert;
|
||||
char *cert_hash;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MD *algo_type;
|
||||
const char *algo_name;
|
||||
#else
|
||||
const EVP_MD *algo_type = NULL;
|
||||
#endif
|
||||
unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
|
||||
unsigned int hash_size;
|
||||
int algo_nid;
|
||||
@@ -2311,6 +2316,25 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
|
||||
* (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
|
||||
* is used, the same hash as the signature algorithm is used.
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
switch (algo_nid)
|
||||
{
|
||||
case NID_md5:
|
||||
case NID_sha1:
|
||||
algo_name = "SHA256";
|
||||
break;
|
||||
default:
|
||||
algo_name = OBJ_nid2sn(algo_nid);
|
||||
if (algo_name == NULL)
|
||||
elog(ERROR, "could not find digest for NID %s",
|
||||
OBJ_nid2sn(algo_nid));
|
||||
break;
|
||||
}
|
||||
|
||||
algo_type = EVP_MD_fetch(NULL, algo_name, NULL);
|
||||
if (algo_type == NULL)
|
||||
elog(ERROR, "could not fetch digest \"%s\"", algo_name);
|
||||
#else
|
||||
switch (algo_nid)
|
||||
{
|
||||
case NID_md5:
|
||||
@@ -2324,10 +2348,20 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
|
||||
OBJ_nid2sn(algo_nid));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* generate and save the certificate hash */
|
||||
if (!X509_digest(server_cert, algo_type, hash, &hash_size))
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MD_free(algo_type);
|
||||
#endif
|
||||
elog(ERROR, "could not generate server certificate hash");
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MD_free(algo_type);
|
||||
#endif
|
||||
|
||||
cert_hash = palloc(hash_size);
|
||||
memcpy(cert_hash, hash, hash_size);
|
||||
|
||||
@@ -371,7 +371,12 @@ char *
|
||||
pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
|
||||
{
|
||||
X509 *peer_cert;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MD *algo_type;
|
||||
const char *algo_name;
|
||||
#else
|
||||
const EVP_MD *algo_type;
|
||||
#endif
|
||||
unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
|
||||
unsigned int hash_size;
|
||||
int algo_nid;
|
||||
@@ -406,6 +411,31 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
|
||||
* (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
|
||||
* is used, the same hash as the signature algorithm is used.
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
switch (algo_nid)
|
||||
{
|
||||
case NID_md5:
|
||||
case NID_sha1:
|
||||
algo_name = "SHA256";
|
||||
break;
|
||||
default:
|
||||
algo_name = OBJ_nid2sn(algo_nid);
|
||||
if (algo_name == NULL)
|
||||
{
|
||||
libpq_append_conn_error(conn, "could not find digest for NID %s",
|
||||
OBJ_nid2sn(algo_nid));
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
algo_type = EVP_MD_fetch(NULL, algo_name, NULL);
|
||||
if (algo_type == NULL)
|
||||
{
|
||||
libpq_append_conn_error(conn, "could not fetch digest \"%s\"", algo_name);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
switch (algo_nid)
|
||||
{
|
||||
case NID_md5:
|
||||
@@ -422,13 +452,21 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MD_free(algo_type);
|
||||
#endif
|
||||
libpq_append_conn_error(conn, "could not generate peer certificate hash");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MD_free(algo_type);
|
||||
#endif
|
||||
|
||||
/* save result */
|
||||
cert_hash = malloc(hash_size);
|
||||
if (cert_hash == NULL)
|
||||
|
||||
Reference in New Issue
Block a user