1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Support OpenSSL 1.1.0 in 9.3 and 9.2.

This commit back-patches the equivalent of the 9.5-branch commits
e2838c580 and 48e5ba61e, so that we can work with OpenSSL 1.1.0
in all supported branches.

Original patches by Andreas Karlsson and Heikki Linnakangas,
back-patching work by Andreas Karlsson.

Patch: https://postgr.es/m/0c817abb-3f7d-20fb-583a-58f7593a0bea@proxel.se
Discussion: https://postgr.es/m/5129.1492293840@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2017-04-17 13:52:42 -04:00
parent fbfeceb253
commit 4e91330dac
11 changed files with 464 additions and 88 deletions

View File

@ -620,15 +620,6 @@ px_find_cipher(const char *name, PX_Cipher **res)
* Randomness provider
*/
/*
* Use always strong randomness.
*/
int
px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
{
return px_get_random_bytes(dst, count);
}
static time_t seed_time = 0;
static time_t check_time = 0;

View File

@ -40,6 +40,9 @@
#include <openssl/rand.h>
#include <openssl/err.h>
#include "utils/memutils.h"
#include "utils/resowner.h"
/*
* Max lengths we might want to handle.
*/
@ -199,18 +202,73 @@ compat_find_digest(const char *name, PX_MD **res)
* Hashes
*/
/*
* To make sure we don't leak OpenSSL handles on abort, we keep OSSLDigest
* objects in a linked list, allocated in TopMemoryContext. We use the
* ResourceOwner mechanism to free them on abort.
*/
typedef struct OSSLDigest
{
const EVP_MD *algo;
EVP_MD_CTX ctx;
EVP_MD_CTX *ctx;
ResourceOwner owner;
struct OSSLDigest *next;
struct OSSLDigest *prev;
} OSSLDigest;
static OSSLDigest *open_digests = NULL;
static bool resowner_callback_registered = false;
static void
free_openssldigest(OSSLDigest *digest)
{
EVP_MD_CTX_destroy(digest->ctx);
if (digest->prev)
digest->prev->next = digest->next;
else
open_digests = digest->next;
if (digest->next)
digest->next->prev = digest->prev;
pfree(digest);
}
/*
* Close any open OpenSSL handles on abort.
*/
static void
digest_free_callback(ResourceReleasePhase phase,
bool isCommit,
bool isTopLevel,
void *arg)
{
OSSLDigest *curr;
OSSLDigest *next;
if (phase != RESOURCE_RELEASE_AFTER_LOCKS)
return;
next = open_digests;
while (next)
{
curr = next;
next = curr->next;
if (curr->owner == CurrentResourceOwner)
{
if (isCommit)
elog(WARNING, "pgcrypto digest reference leak: digest %p still referenced", curr);
free_openssldigest(curr);
}
}
}
static unsigned
digest_result_size(PX_MD *h)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
return EVP_MD_CTX_size(&digest->ctx);
return EVP_MD_CTX_size(digest->ctx);
}
static unsigned
@ -218,7 +276,7 @@ digest_block_size(PX_MD *h)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
return EVP_MD_CTX_block_size(&digest->ctx);
return EVP_MD_CTX_block_size(digest->ctx);
}
static void
@ -226,7 +284,7 @@ digest_reset(PX_MD *h)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL);
EVP_DigestInit_ex(digest->ctx, digest->algo, NULL);
}
static void
@ -234,7 +292,7 @@ digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
EVP_DigestUpdate(&digest->ctx, data, dlen);
EVP_DigestUpdate(digest->ctx, data, dlen);
}
static void
@ -242,7 +300,7 @@ digest_finish(PX_MD *h, uint8 *dst)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
EVP_DigestFinal_ex(&digest->ctx, dst, NULL);
EVP_DigestFinal_ex(digest->ctx, dst, NULL);
}
static void
@ -250,9 +308,7 @@ digest_free(PX_MD *h)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
EVP_MD_CTX_cleanup(&digest->ctx);
px_free(digest);
free_openssldigest(digest);
px_free(h);
}
@ -264,6 +320,7 @@ int
px_find_digest(const char *name, PX_MD **res)
{
const EVP_MD *md;
EVP_MD_CTX *ctx;
PX_MD *h;
OSSLDigest *digest;
@ -273,17 +330,43 @@ px_find_digest(const char *name, PX_MD **res)
OpenSSL_add_all_algorithms();
}
if (!resowner_callback_registered)
{
RegisterResourceReleaseCallback(digest_free_callback, NULL);
resowner_callback_registered = true;
}
md = EVP_get_digestbyname(name);
if (md == NULL)
return compat_find_digest(name, res);
digest = px_alloc(sizeof(*digest));
digest->algo = md;
/*
* Create an OSSLDigest object, an OpenSSL MD object, and a PX_MD object.
* The order is crucial, to make sure we don't leak anything on
* out-of-memory or other error.
*/
digest = MemoryContextAlloc(TopMemoryContext, sizeof(*digest));
EVP_MD_CTX_init(&digest->ctx);
if (EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL) == 0)
ctx = EVP_MD_CTX_create();
if (!ctx)
{
pfree(digest);
return -1;
}
if (EVP_DigestInit_ex(ctx, md, NULL) == 0)
{
pfree(digest);
return -1;
}
digest->algo = md;
digest->ctx = ctx;
digest->owner = CurrentResourceOwner;
digest->next = open_digests;
digest->prev = NULL;
open_digests = digest;
/* The PX_MD object is allocated in the current memory context. */
h = px_alloc(sizeof(*h));
h->result_size = digest_result_size;
h->block_size = digest_block_size;
@ -987,7 +1070,13 @@ static void
init_openssl_rand(void)
{
if (RAND_get_rand_method() == NULL)
{
#ifdef HAVE_RAND_OPENSSL
RAND_set_rand_method(RAND_OpenSSL());
#else
RAND_set_rand_method(RAND_SSLeay());
#endif
}
openssl_random_init = 1;
}
@ -1006,21 +1095,6 @@ px_get_random_bytes(uint8 *dst, unsigned count)
return PXE_OSSL_RAND_ERROR;
}
int
px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
{
int res;
if (!openssl_random_init)
init_openssl_rand();
res = RAND_pseudo_bytes(dst, count);
if (res == 0 || res == 1)
return count;
return PXE_OSSL_RAND_ERROR;
}
int
px_add_entropy(const uint8 *data, unsigned count)
{

View File

@ -223,13 +223,13 @@ pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
case 0:
break;
case 1:
res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
res = px_get_random_bytes(s2k->salt, PGP_S2K_SALT);
break;
case 3:
res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
res = px_get_random_bytes(s2k->salt, PGP_S2K_SALT);
if (res < 0)
break;
res = px_get_pseudo_random_bytes(&tmp, 1);
res = px_get_random_bytes(&tmp, 1);
if (res < 0)
break;
s2k->iter = decide_count(tmp);

View File

@ -153,7 +153,7 @@ px_gen_salt(const char *salt_type, char *buf, int rounds)
return PXE_BAD_SALT_ROUNDS;
}
res = px_get_pseudo_random_bytes((uint8 *) rbuf, g->input_len);
res = px_get_random_bytes((uint8 *) rbuf, g->input_len);
if (res < 0)
return res;

View File

@ -190,7 +190,6 @@ int px_find_cipher(const char *name, PX_Cipher **res);
int px_find_combo(const char *name, PX_Combo **res);
int px_get_random_bytes(uint8 *dst, unsigned count);
int px_get_pseudo_random_bytes(uint8 *dst, unsigned count);
int px_add_entropy(const uint8 *data, unsigned count);
unsigned px_acquire_system_randomness(uint8 *dst);