summaryrefslogtreecommitdiff
path: root/src/common/cryptohash_openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/cryptohash_openssl.c')
-rw-r--r--src/common/cryptohash_openssl.c128
1 files changed, 80 insertions, 48 deletions
diff --git a/src/common/cryptohash_openssl.c b/src/common/cryptohash_openssl.c
index 33f17cac33d..9d9f74b086c 100644
--- a/src/common/cryptohash_openssl.c
+++ b/src/common/cryptohash_openssl.c
@@ -21,9 +21,14 @@
#include "postgres_fe.h"
#endif
-#include <openssl/sha.h>
+#include <openssl/evp.h>
#include "common/cryptohash.h"
+#ifndef FRONTEND
+#include "utils/memutils.h"
+#include "utils/resowner.h"
+#include "utils/resowner_private.h"
+#endif
/*
* In backend, use palloc/pfree to ease the error handling. In frontend,
@@ -38,6 +43,21 @@
#endif
/*
+ * Internal structure for pg_cryptohash_ctx->data.
+ *
+ * This tracks the resource owner associated to each EVP context data
+ * for the backend.
+ */
+typedef struct pg_cryptohash_state
+{
+ EVP_MD_CTX *evpctx;
+
+#ifndef FRONTEND
+ ResourceOwner resowner;
+#endif
+} pg_cryptohash_state;
+
+/*
* pg_cryptohash_create
*
* Allocate a hash context. Returns NULL on failure for an OOM. The
@@ -47,32 +67,53 @@ pg_cryptohash_ctx *
pg_cryptohash_create(pg_cryptohash_type type)
{
pg_cryptohash_ctx *ctx;
+ pg_cryptohash_state *state;
ctx = ALLOC(sizeof(pg_cryptohash_ctx));
if (ctx == NULL)
return NULL;
- ctx->type = type;
-
- switch (type)
+ state = ALLOC(sizeof(pg_cryptohash_state));
+ if (state == NULL)
{
- case PG_SHA224:
- case PG_SHA256:
- ctx->data = ALLOC(sizeof(SHA256_CTX));
- break;
- case PG_SHA384:
- case PG_SHA512:
- ctx->data = ALLOC(sizeof(SHA512_CTX));
- break;
+ explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
+ FREE(ctx);
+ return NULL;
}
- if (ctx->data == NULL)
+ ctx->data = state;
+ ctx->type = type;
+
+#ifndef FRONTEND
+ ResourceOwnerEnlargeCryptoHash(CurrentResourceOwner);
+#endif
+
+ /*
+ * Initialization takes care of assigning the correct type for OpenSSL.
+ */
+ state->evpctx = EVP_MD_CTX_create();
+
+ if (state->evpctx == NULL)
{
+ explicit_bzero(state, sizeof(pg_cryptohash_state));
explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#else
+ FREE(state);
FREE(ctx);
return NULL;
+#endif
}
+#ifndef FRONTEND
+ state->resowner = CurrentResourceOwner;
+ ResourceOwnerRememberCryptoHash(CurrentResourceOwner,
+ PointerGetDatum(ctx));
+#endif
+
return ctx;
}
@@ -85,23 +126,26 @@ int
pg_cryptohash_init(pg_cryptohash_ctx *ctx)
{
int status = 0;
+ pg_cryptohash_state *state;
if (ctx == NULL)
return 0;
+ state = (pg_cryptohash_state *) ctx->data;
+
switch (ctx->type)
{
case PG_SHA224:
- status = SHA224_Init((SHA256_CTX *) ctx->data);
+ status = EVP_DigestInit_ex(state->evpctx, EVP_sha224(), NULL);
break;
case PG_SHA256:
- status = SHA256_Init((SHA256_CTX *) ctx->data);
+ status = EVP_DigestInit_ex(state->evpctx, EVP_sha256(), NULL);
break;
case PG_SHA384:
- status = SHA384_Init((SHA512_CTX *) ctx->data);
+ status = EVP_DigestInit_ex(state->evpctx, EVP_sha384(), NULL);
break;
case PG_SHA512:
- status = SHA512_Init((SHA512_CTX *) ctx->data);
+ status = EVP_DigestInit_ex(state->evpctx, EVP_sha512(), NULL);
break;
}
@@ -120,25 +164,13 @@ int
pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
{
int status = 0;
+ pg_cryptohash_state *state;
if (ctx == NULL)
return 0;
- switch (ctx->type)
- {
- case PG_SHA224:
- status = SHA224_Update((SHA256_CTX *) ctx->data, data, len);
- break;
- case PG_SHA256:
- status = SHA256_Update((SHA256_CTX *) ctx->data, data, len);
- break;
- case PG_SHA384:
- status = SHA384_Update((SHA512_CTX *) ctx->data, data, len);
- break;
- case PG_SHA512:
- status = SHA512_Update((SHA512_CTX *) ctx->data, data, len);
- break;
- }
+ state = (pg_cryptohash_state *) ctx->data;
+ status = EVP_DigestUpdate(state->evpctx, data, len);
/* OpenSSL internals return 1 on success, 0 on failure */
if (status <= 0)
@@ -155,25 +187,13 @@ int
pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest)
{
int status = 0;
+ pg_cryptohash_state *state;
if (ctx == NULL)
return 0;
- switch (ctx->type)
- {
- case PG_SHA224:
- status = SHA224_Final(dest, (SHA256_CTX *) ctx->data);
- break;
- case PG_SHA256:
- status = SHA256_Final(dest, (SHA256_CTX *) ctx->data);
- break;
- case PG_SHA384:
- status = SHA384_Final(dest, (SHA512_CTX *) ctx->data);
- break;
- case PG_SHA512:
- status = SHA512_Final(dest, (SHA512_CTX *) ctx->data);
- break;
- }
+ state = (pg_cryptohash_state *) ctx->data;
+ status = EVP_DigestFinal_ex(state->evpctx, dest, 0);
/* OpenSSL internals return 1 on success, 0 on failure */
if (status <= 0)
@@ -189,9 +209,21 @@ pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest)
void
pg_cryptohash_free(pg_cryptohash_ctx *ctx)
{
+ pg_cryptohash_state *state;
+
if (ctx == NULL)
return;
- FREE(ctx->data);
+
+ state = (pg_cryptohash_state *) ctx->data;
+ EVP_MD_CTX_destroy(state->evpctx);
+
+#ifndef FRONTEND
+ ResourceOwnerForgetCryptoHash(state->resowner,
+ PointerGetDatum(ctx));
+#endif
+
+ explicit_bzero(state, sizeof(pg_cryptohash_state));
explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
+ FREE(state);
FREE(ctx);
}