diff --git a/contrib/pgcrypto/internal-sha2.c b/contrib/pgcrypto/internal-sha2.c index 0fe53e15af..c0d9eea731 100644 --- a/contrib/pgcrypto/internal-sha2.c +++ b/contrib/pgcrypto/internal-sha2.c @@ -118,7 +118,7 @@ int_sha2_finish(PX_MD *h, uint8 *dst) { pg_cryptohash_ctx *ctx = (pg_cryptohash_ctx *) h->p.ptr; - if (pg_cryptohash_final(ctx, dst) < 0) + if (pg_cryptohash_final(ctx, dst, PG_SHA224_DIGEST_LENGTH) < 0) elog(ERROR, "could not finalize %s context", "SHA2"); } diff --git a/contrib/pgcrypto/internal.c b/contrib/pgcrypto/internal.c index ef6ce2fb1e..955501b4d4 100644 --- a/contrib/pgcrypto/internal.c +++ b/contrib/pgcrypto/internal.c @@ -106,7 +106,7 @@ int_md5_finish(PX_MD *h, uint8 *dst) { pg_cryptohash_ctx *ctx = (pg_cryptohash_ctx *) h->p.ptr; - if (pg_cryptohash_final(ctx, dst) < 0) + if (pg_cryptohash_final(ctx, dst, MD5_DIGEST_LENGTH) < 0) elog(ERROR, "could not finalize %s context", "MD5"); } @@ -156,7 +156,7 @@ int_sha1_finish(PX_MD *h, uint8 *dst) { pg_cryptohash_ctx *ctx = (pg_cryptohash_ctx *) h->p.ptr; - if (pg_cryptohash_final(ctx, dst) < 0) + if (pg_cryptohash_final(ctx, dst, SHA1_DIGEST_LENGTH) < 0) elog(ERROR, "could not finalize %s context", "SHA1"); } diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c index 8d857f39df..284b03c50e 100644 --- a/src/backend/libpq/auth-scram.c +++ b/src/backend/libpq/auth-scram.c @@ -1120,7 +1120,7 @@ verify_client_proof(scram_state *state) scram_HMAC_update(&ctx, state->client_final_message_without_proof, strlen(state->client_final_message_without_proof)) < 0 || - scram_HMAC_final(ClientSignature, &ctx) < 0) + scram_HMAC_final(&ctx, ClientSignature) < 0) { elog(ERROR, "could not calculate client signature"); } @@ -1374,7 +1374,7 @@ build_server_final_message(scram_state *state) scram_HMAC_update(&ctx, state->client_final_message_without_proof, strlen(state->client_final_message_without_proof)) < 0 || - scram_HMAC_final(ServerSignature, &ctx) < 0) + scram_HMAC_final(&ctx, ServerSignature) < 0) { elog(ERROR, "could not calculate server signature"); } @@ -1429,7 +1429,8 @@ scram_mock_salt(const char *username) if (pg_cryptohash_init(ctx) < 0 || pg_cryptohash_update(ctx, (uint8 *) username, strlen(username)) < 0 || pg_cryptohash_update(ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN) < 0 || - pg_cryptohash_final(ctx, sha_digest) < 0) + pg_cryptohash_final(ctx, sha_digest, + sizeof(sha_digest) - 1) < 0) { pg_cryptohash_free(ctx); return NULL; diff --git a/src/backend/replication/backup_manifest.c b/src/backend/replication/backup_manifest.c index 0cefd181b5..5516ed4948 100644 --- a/src/backend/replication/backup_manifest.c +++ b/src/backend/replication/backup_manifest.c @@ -330,7 +330,8 @@ SendBackupManifest(backup_manifest_info *manifest) * twice. */ manifest->still_checksumming = false; - if (pg_cryptohash_final(manifest->manifest_ctx, checksumbuf) < 0) + if (pg_cryptohash_final(manifest->manifest_ctx, checksumbuf, + sizeof(checksumbuf) - 1) < 0) elog(ERROR, "failed to finalize checksum of backup manifest"); AppendStringToManifest(manifest, "\"Manifest-Checksum\": \""); dstlen = pg_hex_enc_len(PG_SHA256_DIGEST_LENGTH); diff --git a/src/backend/utils/adt/cryptohashfuncs.c b/src/backend/utils/adt/cryptohashfuncs.c index 152adcbfb4..6a0f0258e6 100644 --- a/src/backend/utils/adt/cryptohashfuncs.c +++ b/src/backend/utils/adt/cryptohashfuncs.c @@ -114,7 +114,8 @@ cryptohash_internal(pg_cryptohash_type type, bytea *input) elog(ERROR, "could not initialize %s context", typestr); if (pg_cryptohash_update(ctx, data, len) < 0) elog(ERROR, "could not update %s context", typestr); - if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result)) < 0) + if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result), + digest_len) < 0) elog(ERROR, "could not finalize %s context", typestr); pg_cryptohash_free(ctx); diff --git a/src/bin/pg_verifybackup/parse_manifest.c b/src/bin/pg_verifybackup/parse_manifest.c index db2fa90cfe..28c1bfbe5c 100644 --- a/src/bin/pg_verifybackup/parse_manifest.c +++ b/src/bin/pg_verifybackup/parse_manifest.c @@ -659,7 +659,8 @@ verify_manifest_checksum(JsonManifestParseState *parse, char *buffer, context->error_cb(context, "could not initialize checksum of manifest"); if (pg_cryptohash_update(manifest_ctx, (uint8 *) buffer, penultimate_newline + 1) < 0) context->error_cb(context, "could not update checksum of manifest"); - if (pg_cryptohash_final(manifest_ctx, manifest_checksum_actual) < 0) + if (pg_cryptohash_final(manifest_ctx, manifest_checksum_actual, + PG_SHA256_DIGEST_LENGTH) < 0) context->error_cb(context, "could not finalize checksum of manifest"); /* Now verify it. */ diff --git a/src/common/checksum_helper.c b/src/common/checksum_helper.c index a895e2e285..54b684d5e8 100644 --- a/src/common/checksum_helper.c +++ b/src/common/checksum_helper.c @@ -198,25 +198,29 @@ pg_checksum_final(pg_checksum_context *context, uint8 *output) memcpy(output, &context->raw_context.c_crc32c, retval); break; case CHECKSUM_TYPE_SHA224: - if (pg_cryptohash_final(context->raw_context.c_sha2, output) < 0) + if (pg_cryptohash_final(context->raw_context.c_sha2, + output, PG_SHA224_DIGEST_LENGTH) < 0) return -1; pg_cryptohash_free(context->raw_context.c_sha2); retval = PG_SHA224_DIGEST_LENGTH; break; case CHECKSUM_TYPE_SHA256: - if (pg_cryptohash_final(context->raw_context.c_sha2, output) < 0) + if (pg_cryptohash_final(context->raw_context.c_sha2, + output, PG_SHA256_DIGEST_LENGTH) < 0) return -1; pg_cryptohash_free(context->raw_context.c_sha2); retval = PG_SHA256_DIGEST_LENGTH; break; case CHECKSUM_TYPE_SHA384: - if (pg_cryptohash_final(context->raw_context.c_sha2, output) < 0) + if (pg_cryptohash_final(context->raw_context.c_sha2, + output, PG_SHA384_DIGEST_LENGTH) < 0) return -1; pg_cryptohash_free(context->raw_context.c_sha2); retval = PG_SHA384_DIGEST_LENGTH; break; case CHECKSUM_TYPE_SHA512: - if (pg_cryptohash_final(context->raw_context.c_sha2, output) < 0) + if (pg_cryptohash_final(context->raw_context.c_sha2, + output, PG_SHA512_DIGEST_LENGTH) < 0) return -1; pg_cryptohash_free(context->raw_context.c_sha2); retval = PG_SHA512_DIGEST_LENGTH; diff --git a/src/common/cryptohash.c b/src/common/cryptohash.c index 5b2c050d79..9ab36003c9 100644 --- a/src/common/cryptohash.c +++ b/src/common/cryptohash.c @@ -161,11 +161,11 @@ pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len) * pg_cryptohash_final * * Finalize a hash context. Note that this implementation is designed - * to never fail, so this always returns 0 except if the caller has - * given a NULL context. + * to never fail, but note that this would fail if the destination buffer + * is not large enough. */ int -pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest) +pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len) { if (ctx == NULL) return -1; @@ -173,21 +173,33 @@ pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest) switch (ctx->type) { case PG_MD5: + if (len < MD5_DIGEST_LENGTH) + return -1; pg_md5_final(&ctx->data.md5, dest); break; case PG_SHA1: + if (len < SHA1_DIGEST_LENGTH) + return -1; pg_sha1_final(&ctx->data.sha1, dest); break; case PG_SHA224: + if (len < PG_SHA224_DIGEST_LENGTH) + return -1; pg_sha224_final(&ctx->data.sha224, dest); break; case PG_SHA256: + if (len < PG_SHA256_DIGEST_LENGTH) + return -1; pg_sha256_final(&ctx->data.sha256, dest); break; case PG_SHA384: + if (len < PG_SHA384_DIGEST_LENGTH) + return -1; pg_sha384_final(&ctx->data.sha384, dest); break; case PG_SHA512: + if (len < PG_SHA512_DIGEST_LENGTH) + return -1; pg_sha512_final(&ctx->data.sha512, dest); break; } diff --git a/src/common/cryptohash_openssl.c b/src/common/cryptohash_openssl.c index 006e867403..643cc7aea2 100644 --- a/src/common/cryptohash_openssl.c +++ b/src/common/cryptohash_openssl.c @@ -24,6 +24,9 @@ #include #include "common/cryptohash.h" +#include "common/md5.h" +#include "common/sha1.h" +#include "common/sha2.h" #ifndef FRONTEND #include "utils/memutils.h" #include "utils/resowner.h" @@ -181,13 +184,41 @@ pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len) * Finalize a hash context. Returns 0 on success, and -1 on failure. */ int -pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest) +pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len) { int status = 0; if (ctx == NULL) return -1; + switch (ctx->type) + { + case PG_MD5: + if (len < MD5_DIGEST_LENGTH) + return -1; + break; + case PG_SHA1: + if (len < SHA1_DIGEST_LENGTH) + return -1; + break; + case PG_SHA224: + if (len < PG_SHA224_DIGEST_LENGTH) + return -1; + break; + case PG_SHA256: + if (len < PG_SHA256_DIGEST_LENGTH) + return -1; + break; + case PG_SHA384: + if (len < PG_SHA384_DIGEST_LENGTH) + return -1; + break; + case PG_SHA512: + if (len < PG_SHA512_DIGEST_LENGTH) + return -1; + break; + } + status = EVP_DigestFinal_ex(ctx->evpctx, dest, 0); /* OpenSSL internals return 1 on success, 0 on failure */ diff --git a/src/common/md5_common.c b/src/common/md5_common.c index b01c95ebb6..6a7f57031e 100644 --- a/src/common/md5_common.c +++ b/src/common/md5_common.c @@ -78,7 +78,8 @@ pg_md5_hash(const void *buff, size_t len, char *hexsum) if (pg_cryptohash_init(ctx) < 0 || pg_cryptohash_update(ctx, buff, len) < 0 || - pg_cryptohash_final(ctx, sum) < 0) + pg_cryptohash_final(ctx, sum, + sizeof(sum) - 1) < 0) { pg_cryptohash_free(ctx); return false; @@ -100,7 +101,7 @@ pg_md5_binary(const void *buff, size_t len, void *outbuf) if (pg_cryptohash_init(ctx) < 0 || pg_cryptohash_update(ctx, buff, len) < 0 || - pg_cryptohash_final(ctx, outbuf) < 0) + pg_cryptohash_final(ctx, outbuf, MD5_DIGEST_LENGTH) < 0) { pg_cryptohash_free(ctx); return false; diff --git a/src/common/scram-common.c b/src/common/scram-common.c index 3f406d4e4d..7ac5810cf6 100644 --- a/src/common/scram-common.c +++ b/src/common/scram-common.c @@ -51,7 +51,8 @@ scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen) return -1; if (pg_cryptohash_init(sha256_ctx) < 0 || pg_cryptohash_update(sha256_ctx, key, keylen) < 0 || - pg_cryptohash_final(sha256_ctx, keybuf) < 0) + pg_cryptohash_final(sha256_ctx, keybuf, + sizeof(keybuf) - 1) < 0) { pg_cryptohash_free(sha256_ctx); return -1; @@ -106,13 +107,14 @@ scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen) * The hash function used is SHA-256. Returns 0 on success, -1 on failure. */ int -scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx) +scram_HMAC_final(scram_HMAC_ctx *ctx, uint8 *result) { uint8 h[SCRAM_KEY_LEN]; Assert(ctx->sha256ctx != NULL); - if (pg_cryptohash_final(ctx->sha256ctx, h) < 0) + if (pg_cryptohash_final(ctx->sha256ctx, h, + sizeof(h) - 1) < 0) { pg_cryptohash_free(ctx->sha256ctx); return -1; @@ -122,7 +124,8 @@ scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx) if (pg_cryptohash_init(ctx->sha256ctx) < 0 || pg_cryptohash_update(ctx->sha256ctx, ctx->k_opad, SHA256_HMAC_B) < 0 || pg_cryptohash_update(ctx->sha256ctx, h, SCRAM_KEY_LEN) < 0 || - pg_cryptohash_final(ctx->sha256ctx, result) < 0) + pg_cryptohash_final(ctx->sha256ctx, result, + sizeof(result) - 1) < 0) { pg_cryptohash_free(ctx->sha256ctx); return -1; @@ -161,7 +164,7 @@ scram_SaltedPassword(const char *password, if (scram_HMAC_init(&hmac_ctx, (uint8 *) password, password_len) < 0 || scram_HMAC_update(&hmac_ctx, salt, saltlen) < 0 || scram_HMAC_update(&hmac_ctx, (char *) &one, sizeof(uint32)) < 0 || - scram_HMAC_final(Ui_prev, &hmac_ctx) < 0) + scram_HMAC_final(&hmac_ctx, Ui_prev) < 0) { return -1; } @@ -173,7 +176,7 @@ scram_SaltedPassword(const char *password, { if (scram_HMAC_init(&hmac_ctx, (uint8 *) password, password_len) < 0 || scram_HMAC_update(&hmac_ctx, (const char *) Ui_prev, SCRAM_KEY_LEN) < 0 || - scram_HMAC_final(Ui, &hmac_ctx) < 0) + scram_HMAC_final(&hmac_ctx, Ui) < 0) { return -1; } @@ -202,7 +205,7 @@ scram_H(const uint8 *input, int len, uint8 *result) if (pg_cryptohash_init(ctx) < 0 || pg_cryptohash_update(ctx, input, len) < 0 || - pg_cryptohash_final(ctx, result) < 0) + pg_cryptohash_final(ctx, result, SCRAM_KEY_LEN) < 0) { pg_cryptohash_free(ctx); return -1; @@ -222,7 +225,7 @@ scram_ClientKey(const uint8 *salted_password, uint8 *result) if (scram_HMAC_init(&ctx, salted_password, SCRAM_KEY_LEN) < 0 || scram_HMAC_update(&ctx, "Client Key", strlen("Client Key")) < 0 || - scram_HMAC_final(result, &ctx) < 0) + scram_HMAC_final(&ctx, result) < 0) { return -1; } @@ -240,7 +243,7 @@ scram_ServerKey(const uint8 *salted_password, uint8 *result) if (scram_HMAC_init(&ctx, salted_password, SCRAM_KEY_LEN) < 0 || scram_HMAC_update(&ctx, "Server Key", strlen("Server Key")) < 0 || - scram_HMAC_final(result, &ctx) < 0) + scram_HMAC_final(&ctx, result) < 0) { return -1; } diff --git a/src/include/common/cryptohash.h b/src/include/common/cryptohash.h index 32d7784ca5..541dc844c8 100644 --- a/src/include/common/cryptohash.h +++ b/src/include/common/cryptohash.h @@ -32,7 +32,7 @@ typedef struct pg_cryptohash_ctx pg_cryptohash_ctx; extern pg_cryptohash_ctx *pg_cryptohash_create(pg_cryptohash_type type); extern int pg_cryptohash_init(pg_cryptohash_ctx *ctx); extern int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len); -extern int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest); +extern int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len); extern void pg_cryptohash_free(pg_cryptohash_ctx *ctx); #endif /* PG_CRYPTOHASH_H */ diff --git a/src/include/common/scram-common.h b/src/include/common/scram-common.h index 9d684b41e8..9d7d1171b5 100644 --- a/src/include/common/scram-common.h +++ b/src/include/common/scram-common.h @@ -57,7 +57,7 @@ typedef struct extern int scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen); extern int scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen); -extern int scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx); +extern int scram_HMAC_final(scram_HMAC_ctx *ctx, uint8 *result); extern int scram_SaltedPassword(const char *password, const char *salt, int saltlen, int iterations, uint8 *result); diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c index 002469540a..f425140170 100644 --- a/src/interfaces/libpq/fe-auth-scram.c +++ b/src/interfaces/libpq/fe-auth-scram.c @@ -798,7 +798,7 @@ calculate_client_proof(fe_scram_state *state, scram_HMAC_update(&ctx, client_final_message_without_proof, strlen(client_final_message_without_proof)) < 0 || - scram_HMAC_final(ClientSignature, &ctx) < 0) + scram_HMAC_final(&ctx, ClientSignature) < 0) { return false; } @@ -836,7 +836,7 @@ verify_server_signature(fe_scram_state *state, bool *match) scram_HMAC_update(&ctx, state->client_final_message_without_proof, strlen(state->client_final_message_without_proof)) < 0 || - scram_HMAC_final(expected_ServerSignature, &ctx) < 0) + scram_HMAC_final(&ctx, expected_ServerSignature) < 0) { return false; }