diff options
Diffstat (limited to 'src/common/cryptohash_openssl.c')
-rw-r--r-- | src/common/cryptohash_openssl.c | 128 |
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); } |