v2-0001-Rework-SHA2-APIs.patch
text/x-diff
Filename: v2-0001-Rework-SHA2-APIs.patch
Type: text/x-diff
Part: 0
Patch
Format: format-patch
Series: patch v2-0001
Subject: Rework SHA2 APIs
| File | + | − |
|---|---|---|
| contrib/pgcrypto/internal-sha2.c | 40 | 147 |
| src/backend/libpq/auth-scram.c | 57 | 37 |
| src/backend/replication/backup_manifest.c | 27 | 3 |
| src/backend/replication/basebackup.c | 18 | 8 |
| src/backend/utils/adt/cryptohashes.c | 36 | 16 |
| src/bin/pg_verifybackup/parse_manifest.c | 11 | 4 |
| src/bin/pg_verifybackup/pg_verifybackup.c | 22 | 2 |
| src/common/checksum_helper.c | 63 | 16 |
| src/common/scram-common.c | 117 | 49 |
| src/common/sha2.c | 192 | 12 |
| src/common/sha2_openssl.c | 153 | 60 |
| src/include/common/checksum_helper.h | 6 | 6 |
| src/include/common/scram-common.h | 8 | 8 |
| src/include/common/sha2.h | 17 | 43 |
| src/include/replication/backup_manifest.h | 2 | 1 |
| src/interfaces/libpq/fe-auth-scram.c | 65 | 49 |
| src/tools/pgindent/typedefs.list | 1 | 0 |
From e9c82de0b57bf6f3670da37bbf4996553e3ab9ee Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 15 Oct 2020 15:28:20 +0900
Subject: [PATCH v2 1/3] Rework SHA2 APIs
This will make easier a switch to EVP for the OpenSSL SHA2 layer.
(Note for self: this commit has been indented.)
---
src/include/common/checksum_helper.h | 12 +-
src/include/common/scram-common.h | 16 +-
src/include/common/sha2.h | 60 ++----
src/include/replication/backup_manifest.h | 3 +-
src/backend/libpq/auth-scram.c | 94 ++++++----
src/backend/replication/backup_manifest.c | 30 ++-
src/backend/replication/basebackup.c | 26 ++-
src/backend/utils/adt/cryptohashes.c | 52 ++++--
src/common/checksum_helper.c | 79 ++++++--
src/common/scram-common.c | 166 ++++++++++++-----
src/common/sha2.c | 204 +++++++++++++++++++--
src/common/sha2_openssl.c | 213 ++++++++++++++++------
src/bin/pg_verifybackup/parse_manifest.c | 15 +-
src/bin/pg_verifybackup/pg_verifybackup.c | 24 ++-
src/interfaces/libpq/fe-auth-scram.c | 114 +++++++-----
contrib/pgcrypto/internal-sha2.c | 187 ++++---------------
src/tools/pgindent/typedefs.list | 1 +
17 files changed, 835 insertions(+), 461 deletions(-)
diff --git a/src/include/common/checksum_helper.h b/src/include/common/checksum_helper.h
index 48b0745dad..4db7a1cce9 100644
--- a/src/include/common/checksum_helper.h
+++ b/src/include/common/checksum_helper.h
@@ -41,10 +41,10 @@ typedef enum pg_checksum_type
typedef union pg_checksum_raw_context
{
pg_crc32c c_crc32c;
- pg_sha224_ctx c_sha224;
- pg_sha256_ctx c_sha256;
- pg_sha384_ctx c_sha384;
- pg_sha512_ctx c_sha512;
+ pg_sha2_ctx *c_sha224;
+ pg_sha2_ctx *c_sha256;
+ pg_sha2_ctx *c_sha384;
+ pg_sha2_ctx *c_sha512;
} pg_checksum_raw_context;
/*
@@ -66,8 +66,8 @@ typedef struct pg_checksum_context
extern bool pg_checksum_parse_type(char *name, pg_checksum_type *);
extern char *pg_checksum_type_name(pg_checksum_type);
-extern void pg_checksum_init(pg_checksum_context *, pg_checksum_type);
-extern void pg_checksum_update(pg_checksum_context *, const uint8 *input,
+extern int pg_checksum_init(pg_checksum_context *, pg_checksum_type);
+extern int pg_checksum_update(pg_checksum_context *, const uint8 *input,
size_t len);
extern int pg_checksum_final(pg_checksum_context *, uint8 *output);
diff --git a/src/include/common/scram-common.h b/src/include/common/scram-common.h
index 2edae2dd3c..53fc085a38 100644
--- a/src/include/common/scram-common.h
+++ b/src/include/common/scram-common.h
@@ -50,19 +50,19 @@
*/
typedef struct
{
- pg_sha256_ctx sha256ctx;
+ pg_sha2_ctx *sha256ctx;
uint8 k_opad[SHA256_HMAC_B];
} scram_HMAC_ctx;
-extern void scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen);
-extern void scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen);
-extern void scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx);
+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 void scram_SaltedPassword(const char *password, const char *salt,
+extern int scram_SaltedPassword(const char *password, const char *salt,
int saltlen, int iterations, uint8 *result);
-extern void scram_H(const uint8 *str, int len, uint8 *result);
-extern void scram_ClientKey(const uint8 *salted_password, uint8 *result);
-extern void scram_ServerKey(const uint8 *salted_password, uint8 *result);
+extern int scram_H(const uint8 *str, int len, uint8 *result);
+extern int scram_ClientKey(const uint8 *salted_password, uint8 *result);
+extern int scram_ServerKey(const uint8 *salted_password, uint8 *result);
extern char *scram_build_secret(const char *salt, int saltlen, int iterations,
const char *password);
diff --git a/src/include/common/sha2.h b/src/include/common/sha2.h
index 9c4abf777d..76940cba46 100644
--- a/src/include/common/sha2.h
+++ b/src/include/common/sha2.h
@@ -50,10 +50,6 @@
#ifndef _PG_SHA2_H_
#define _PG_SHA2_H_
-#ifdef USE_OPENSSL
-#include <openssl/sha.h>
-#endif
-
/*** SHA224/256/384/512 Various Length Definitions ***********************/
#define PG_SHA224_BLOCK_LENGTH 64
#define PG_SHA224_DIGEST_LENGTH 28
@@ -69,47 +65,25 @@
#define PG_SHA512_DIGEST_STRING_LENGTH (PG_SHA512_DIGEST_LENGTH * 2 + 1)
/* Context Structures for SHA224/256/384/512 */
-#ifdef USE_OPENSSL
-typedef SHA256_CTX pg_sha256_ctx;
-typedef SHA512_CTX pg_sha512_ctx;
-typedef SHA256_CTX pg_sha224_ctx;
-typedef SHA512_CTX pg_sha384_ctx;
-#else
-typedef struct pg_sha256_ctx
+typedef enum
{
- uint32 state[8];
- uint64 bitcount;
- uint8 buffer[PG_SHA256_BLOCK_LENGTH];
-} pg_sha256_ctx;
-typedef struct pg_sha512_ctx
+ PG_SHA224 = 0,
+ PG_SHA256,
+ PG_SHA384,
+ PG_SHA512
+} pg_sha2_type;
+
+typedef struct pg_sha2_ctx
{
- uint64 state[8];
- uint64 bitcount[2];
- uint8 buffer[PG_SHA512_BLOCK_LENGTH];
-} pg_sha512_ctx;
-typedef struct pg_sha256_ctx pg_sha224_ctx;
-typedef struct pg_sha512_ctx pg_sha384_ctx;
-#endif /* USE_OPENSSL */
+ pg_sha2_type type;
+ /* private area used by each SHA2 implementation */
+ void *data;
+} pg_sha2_ctx;
-/* Interface routines for SHA224/256/384/512 */
-extern void pg_sha224_init(pg_sha224_ctx *ctx);
-extern void pg_sha224_update(pg_sha224_ctx *ctx, const uint8 *input0,
- size_t len);
-extern void pg_sha224_final(pg_sha224_ctx *ctx, uint8 *dest);
-
-extern void pg_sha256_init(pg_sha256_ctx *ctx);
-extern void pg_sha256_update(pg_sha256_ctx *ctx, const uint8 *input0,
- size_t len);
-extern void pg_sha256_final(pg_sha256_ctx *ctx, uint8 *dest);
-
-extern void pg_sha384_init(pg_sha384_ctx *ctx);
-extern void pg_sha384_update(pg_sha384_ctx *ctx,
- const uint8 *, size_t len);
-extern void pg_sha384_final(pg_sha384_ctx *ctx, uint8 *dest);
-
-extern void pg_sha512_init(pg_sha512_ctx *ctx);
-extern void pg_sha512_update(pg_sha512_ctx *ctx, const uint8 *input0,
- size_t len);
-extern void pg_sha512_final(pg_sha512_ctx *ctx, uint8 *dest);
+extern pg_sha2_ctx *pg_sha2_create(pg_sha2_type type);
+extern int pg_sha2_init(pg_sha2_ctx *ctx);
+extern int pg_sha2_update(pg_sha2_ctx *ctx, const uint8 *data, size_t len);
+extern int pg_sha2_final(pg_sha2_ctx *ctx, uint8 *dest);
+extern void pg_sha2_free(pg_sha2_ctx *ctx);
#endif /* _PG_SHA2_H_ */
diff --git a/src/include/replication/backup_manifest.h b/src/include/replication/backup_manifest.h
index fb1291cbe4..e427a3e9fa 100644
--- a/src/include/replication/backup_manifest.h
+++ b/src/include/replication/backup_manifest.h
@@ -28,7 +28,7 @@ typedef struct backup_manifest_info
{
BufFile *buffile;
pg_checksum_type checksum_type;
- pg_sha256_ctx manifest_ctx;
+ pg_sha2_ctx *manifest_ctx;
uint64 manifest_size;
bool force_encode;
bool first_file;
@@ -48,5 +48,6 @@ extern void AddWALInfoToBackupManifest(backup_manifest_info *manifest,
TimeLineID starttli, XLogRecPtr endptr,
TimeLineID endtli);
extern void SendBackupManifest(backup_manifest_info *manifest);
+extern void FreeBackupManifest(backup_manifest_info *manifest);
#endif
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 0f79b28bb5..ed731b1674 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -527,8 +527,10 @@ scram_verify_plain_password(const char *username, const char *password,
password = prep_password;
/* Compute Server Key based on the user-supplied plaintext password */
- scram_SaltedPassword(password, salt, saltlen, iterations, salted_password);
- scram_ServerKey(salted_password, computed_key);
+ if (scram_SaltedPassword(password, salt, saltlen, iterations,
+ salted_password) < 0 ||
+ scram_ServerKey(salted_password, computed_key) < 0)
+ elog(ERROR, "could not compute server key");
if (prep_password)
pfree(prep_password);
@@ -653,6 +655,8 @@ mock_scram_secret(const char *username, int *iterations, char **salt,
/* Generate deterministic salt */
raw_salt = scram_mock_salt(username);
+ if (raw_salt == NULL)
+ elog(ERROR, "could not encode salt"); /* same error as follows */
encoded_len = pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN);
/* don't forget the zero-terminator */
@@ -1084,7 +1088,8 @@ verify_final_nonce(scram_state *state)
/*
* Verify the client proof contained in the last message received from
- * client in an exchange.
+ * client in an exchange. Returns true if the verification is a success,
+ * or false for a failure.
*/
static bool
verify_client_proof(scram_state *state)
@@ -1095,27 +1100,33 @@ verify_client_proof(scram_state *state)
scram_HMAC_ctx ctx;
int i;
- /* calculate ClientSignature */
- scram_HMAC_init(&ctx, state->StoredKey, SCRAM_KEY_LEN);
- scram_HMAC_update(&ctx,
- state->client_first_message_bare,
- strlen(state->client_first_message_bare));
- scram_HMAC_update(&ctx, ",", 1);
- scram_HMAC_update(&ctx,
- state->server_first_message,
- strlen(state->server_first_message));
- scram_HMAC_update(&ctx, ",", 1);
- scram_HMAC_update(&ctx,
- state->client_final_message_without_proof,
- strlen(state->client_final_message_without_proof));
- scram_HMAC_final(ClientSignature, &ctx);
+ /*
+ * Calculate ClientSignature. Note that we don't log directly a failure
+ * here even when processing the calculations as this could involve a mock
+ * authentication.
+ */
+ if (scram_HMAC_init(&ctx, state->StoredKey, SCRAM_KEY_LEN) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ scram_HMAC_update(&ctx, ",", 1) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ scram_HMAC_update(&ctx, ",", 1) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->client_final_message_without_proof,
+ strlen(state->client_final_message_without_proof)) < 0 ||
+ scram_HMAC_final(ClientSignature, &ctx) < 0)
+ elog(ERROR, "could not calculate client signature");
/* Extract the ClientKey that the client calculated from the proof */
for (i = 0; i < SCRAM_KEY_LEN; i++)
ClientKey[i] = state->ClientProof[i] ^ ClientSignature[i];
/* Hash it one more time, and compare with StoredKey */
- scram_H(ClientKey, SCRAM_KEY_LEN, client_StoredKey);
+ if (scram_H(ClientKey, SCRAM_KEY_LEN, client_StoredKey) < 0)
+ elog(ERROR, "could not hash stored key");
if (memcmp(client_StoredKey, state->StoredKey, SCRAM_KEY_LEN) != 0)
return false;
@@ -1346,19 +1357,22 @@ build_server_final_message(scram_state *state)
scram_HMAC_ctx ctx;
/* calculate ServerSignature */
- scram_HMAC_init(&ctx, state->ServerKey, SCRAM_KEY_LEN);
- scram_HMAC_update(&ctx,
- state->client_first_message_bare,
- strlen(state->client_first_message_bare));
- scram_HMAC_update(&ctx, ",", 1);
- scram_HMAC_update(&ctx,
- state->server_first_message,
- strlen(state->server_first_message));
- scram_HMAC_update(&ctx, ",", 1);
- scram_HMAC_update(&ctx,
- state->client_final_message_without_proof,
- strlen(state->client_final_message_without_proof));
- scram_HMAC_final(ServerSignature, &ctx);
+ if (scram_HMAC_init(&ctx, state->ServerKey, SCRAM_KEY_LEN) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ scram_HMAC_update(&ctx, ",", 1) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ scram_HMAC_update(&ctx, ",", 1) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->client_final_message_without_proof,
+ strlen(state->client_final_message_without_proof)) < 0 ||
+ scram_HMAC_final(ServerSignature, &ctx) < 0)
+ {
+ elog(ERROR, "could not calculate server signature");
+ }
siglen = pg_b64_enc_len(SCRAM_KEY_LEN);
/* don't forget the zero-terminator */
@@ -1388,12 +1402,12 @@ build_server_final_message(scram_state *state)
/*
* Deterministically generate salt for mock authentication, using a SHA256
* hash based on the username and a cluster-level secret key. Returns a
- * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN.
+ * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN, or NULL.
*/
static char *
scram_mock_salt(const char *username)
{
- pg_sha256_ctx ctx;
+ pg_sha2_ctx *ctx;
static uint8 sha_digest[PG_SHA256_DIGEST_LENGTH];
char *mock_auth_nonce = GetMockAuthenticationNonce();
@@ -1406,10 +1420,16 @@ scram_mock_salt(const char *username)
StaticAssertStmt(PG_SHA256_DIGEST_LENGTH >= SCRAM_DEFAULT_SALT_LEN,
"salt length greater than SHA256 digest length");
- pg_sha256_init(&ctx);
- pg_sha256_update(&ctx, (uint8 *) username, strlen(username));
- pg_sha256_update(&ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
- pg_sha256_final(&ctx, sha_digest);
+ ctx = pg_sha2_create(PG_SHA256);
+ if (pg_sha2_init(ctx) < 0 ||
+ pg_sha2_update(ctx, (uint8 *) username, strlen(username)) < 0 ||
+ pg_sha2_update(ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN) < 0 ||
+ pg_sha2_final(ctx, sha_digest) < 0)
+ {
+ pg_sha2_free(ctx);
+ return NULL;
+ }
+ pg_sha2_free(ctx);
return (char *) sha_digest;
}
diff --git a/src/backend/replication/backup_manifest.c b/src/backend/replication/backup_manifest.c
index a43c793e28..ccde3238da 100644
--- a/src/backend/replication/backup_manifest.c
+++ b/src/backend/replication/backup_manifest.c
@@ -62,7 +62,14 @@ InitializeBackupManifest(backup_manifest_info *manifest,
else
manifest->buffile = BufFileCreateTemp(false);
manifest->checksum_type = manifest_checksum_type;
- pg_sha256_init(&manifest->manifest_ctx);
+ if (want_manifest == MANIFEST_OPTION_NO)
+ manifest->manifest_ctx = NULL;
+ else
+ {
+ manifest->manifest_ctx = pg_sha2_create(PG_SHA256);
+ if (pg_sha2_init(manifest->manifest_ctx) < 0)
+ elog(ERROR, "failed to initialize checksum of backup manifest");
+ }
manifest->manifest_size = UINT64CONST(0);
manifest->force_encode = (want_manifest == MANIFEST_OPTION_FORCE_ENCODE);
manifest->first_file = true;
@@ -74,6 +81,16 @@ InitializeBackupManifest(backup_manifest_info *manifest,
"\"Files\": [");
}
+/*
+ * Free resources assigned to a backup manifest constructed.
+ */
+void
+FreeBackupManifest(backup_manifest_info *manifest)
+{
+ pg_sha2_free(manifest->manifest_ctx);
+ manifest->manifest_ctx = NULL;
+}
+
/*
* Add an entry to the backup manifest for a file.
*/
@@ -161,6 +178,9 @@ AddFileToBackupManifest(backup_manifest_info *manifest, const char *spcoid,
int checksumlen;
checksumlen = pg_checksum_final(checksum_ctx, checksumbuf);
+ if (checksumlen < 0)
+ elog(ERROR, "could not finalize checksum of file \"%s\"",
+ pathname);
appendStringInfo(&buf,
", \"Checksum-Algorithm\": \"%s\", \"Checksum\": \"",
@@ -305,7 +325,8 @@ SendBackupManifest(backup_manifest_info *manifest)
* twice.
*/
manifest->still_checksumming = false;
- pg_sha256_final(&manifest->manifest_ctx, checksumbuf);
+ if (pg_sha2_final(manifest->manifest_ctx, checksumbuf) < 0)
+ elog(ERROR, "failed to finalize checksum of backup manifest");
AppendStringToManifest(manifest, "\"Manifest-Checksum\": \"");
hex_encode((char *) checksumbuf, sizeof checksumbuf, checksumstringbuf);
checksumstringbuf[PG_SHA256_DIGEST_STRING_LENGTH - 1] = '\0';
@@ -368,7 +389,10 @@ AppendStringToManifest(backup_manifest_info *manifest, char *s)
Assert(manifest != NULL);
if (manifest->still_checksumming)
- pg_sha256_update(&manifest->manifest_ctx, (uint8 *) s, len);
+ {
+ if (pg_sha2_update(manifest->manifest_ctx, (uint8 *) s, len) < 0)
+ elog(ERROR, "failed to update checksum of backup manifest");
+ }
BufFileWrite(manifest->buffile, s, len);
manifest->manifest_size += len;
}
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index b89df01fa7..ddd2138347 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -414,7 +414,7 @@ perform_base_backup(basebackup_options *opt)
if (ti->path == NULL)
{
struct stat statbuf;
- bool sendtblspclinks = true;
+ bool sendtblspclinks = true;
/* In the main tar, include the backup_label first... */
sendFileWithContent(BACKUP_LABEL_FILE, labelfile->data,
@@ -730,6 +730,7 @@ perform_base_backup(basebackup_options *opt)
}
/* clean up the resource owner we created */
+ FreeBackupManifest(&manifest);
WalSndResourceCleanup(true);
pgstat_progress_end_command();
@@ -1094,7 +1095,9 @@ sendFileWithContent(const char *filename, const char *content,
len;
pg_checksum_context checksum_ctx;
- pg_checksum_init(&checksum_ctx, manifest->checksum_type);
+ if (pg_checksum_init(&checksum_ctx, manifest->checksum_type) < 0)
+ elog(ERROR, "could not initialize checksum of file \"%s\"",
+ filename);
len = strlen(content);
@@ -1130,7 +1133,10 @@ sendFileWithContent(const char *filename, const char *content,
update_basebackup_progress(pad);
}
- pg_checksum_update(&checksum_ctx, (uint8 *) content, len);
+ if (pg_checksum_update(&checksum_ctx, (uint8 *) content, len) < 0)
+ elog(ERROR, "could not update checksum of file \"%s\"",
+ filename);
+
AddFileToBackupManifest(manifest, NULL, filename, len,
(pg_time_t) statbuf.st_mtime, &checksum_ctx);
}
@@ -1584,7 +1590,9 @@ sendFile(const char *readfilename, const char *tarfilename,
bool verify_checksum = false;
pg_checksum_context checksum_ctx;
- pg_checksum_init(&checksum_ctx, manifest->checksum_type);
+ if (pg_checksum_init(&checksum_ctx, manifest->checksum_type) < 0)
+ elog(ERROR, "could not initialize checksum of file \"%s\"",
+ readfilename);
fd = OpenTransientFile(readfilename, O_RDONLY | PG_BINARY);
if (fd < 0)
@@ -1758,7 +1766,8 @@ sendFile(const char *readfilename, const char *tarfilename,
update_basebackup_progress(cnt);
/* Also feed it to the checksum machinery. */
- pg_checksum_update(&checksum_ctx, (uint8 *) buf, cnt);
+ if (pg_checksum_update(&checksum_ctx, (uint8 *) buf, cnt) < 0)
+ elog(ERROR, "could not update checksum of base backup");
len += cnt;
throttle(cnt);
@@ -1772,7 +1781,8 @@ sendFile(const char *readfilename, const char *tarfilename,
{
cnt = Min(sizeof(buf), statbuf->st_size - len);
pq_putmessage('d', buf, cnt);
- pg_checksum_update(&checksum_ctx, (uint8 *) buf, cnt);
+ if (pg_checksum_update(&checksum_ctx, (uint8 *) buf, cnt) < 0)
+ elog(ERROR, "could not update checksum of base backup");
update_basebackup_progress(cnt);
len += cnt;
throttle(cnt);
@@ -1780,8 +1790,8 @@ sendFile(const char *readfilename, const char *tarfilename,
}
/*
- * Pad to a block boundary, per tar format requirements. (This small
- * piece of data is probably not worth throttling, and is not checksummed
+ * Pad to a block boundary, per tar format requirements. (This small piece
+ * of data is probably not worth throttling, and is not checksummed
* because it's not actually part of the file.)
*/
pad = tarPaddingBytesRequired(len);
diff --git a/src/backend/utils/adt/cryptohashes.c b/src/backend/utils/adt/cryptohashes.c
index e897660927..16c61b3333 100644
--- a/src/backend/utils/adt/cryptohashes.c
+++ b/src/backend/utils/adt/cryptohashes.c
@@ -78,16 +78,21 @@ sha224_bytea(PG_FUNCTION_ARGS)
bytea *in = PG_GETARG_BYTEA_PP(0);
const uint8 *data;
size_t len;
- pg_sha224_ctx ctx;
+ pg_sha2_ctx *ctx;
unsigned char buf[PG_SHA224_DIGEST_LENGTH];
bytea *result;
len = VARSIZE_ANY_EXHDR(in);
data = (unsigned char *) VARDATA_ANY(in);
- pg_sha224_init(&ctx);
- pg_sha224_update(&ctx, data, len);
- pg_sha224_final(&ctx, buf);
+ ctx = pg_sha2_create(PG_SHA224);
+ if (pg_sha2_init(ctx) < 0)
+ elog(ERROR, "could not initialize %s context", "SHA224");
+ if (pg_sha2_update(ctx, data, len) < 0)
+ elog(ERROR, "could not update %s context", "SHA224");
+ if (pg_sha2_final(ctx, buf) < 0)
+ elog(ERROR, "could not finalize %s context", "SHA224");
+ pg_sha2_free(ctx);
result = palloc(sizeof(buf) + VARHDRSZ);
SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
@@ -102,16 +107,21 @@ sha256_bytea(PG_FUNCTION_ARGS)
bytea *in = PG_GETARG_BYTEA_PP(0);
const uint8 *data;
size_t len;
- pg_sha256_ctx ctx;
+ pg_sha2_ctx *ctx;
unsigned char buf[PG_SHA256_DIGEST_LENGTH];
bytea *result;
len = VARSIZE_ANY_EXHDR(in);
data = (unsigned char *) VARDATA_ANY(in);
- pg_sha256_init(&ctx);
- pg_sha256_update(&ctx, data, len);
- pg_sha256_final(&ctx, buf);
+ ctx = pg_sha2_create(PG_SHA256);
+ if (pg_sha2_init(ctx) < 0)
+ elog(ERROR, "could not initialize %s context", "SHA256");
+ if (pg_sha2_update(ctx, data, len) < 0)
+ elog(ERROR, "could not update %s context", "SHA256");
+ if (pg_sha2_final(ctx, buf) < 0)
+ elog(ERROR, "could not finalize %s context", "SHA256");
+ pg_sha2_free(ctx);
result = palloc(sizeof(buf) + VARHDRSZ);
SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
@@ -126,16 +136,21 @@ sha384_bytea(PG_FUNCTION_ARGS)
bytea *in = PG_GETARG_BYTEA_PP(0);
const uint8 *data;
size_t len;
- pg_sha384_ctx ctx;
+ pg_sha2_ctx *ctx;
unsigned char buf[PG_SHA384_DIGEST_LENGTH];
bytea *result;
len = VARSIZE_ANY_EXHDR(in);
data = (unsigned char *) VARDATA_ANY(in);
- pg_sha384_init(&ctx);
- pg_sha384_update(&ctx, data, len);
- pg_sha384_final(&ctx, buf);
+ ctx = pg_sha2_create(PG_SHA384);
+ if (pg_sha2_init(ctx) < 0)
+ elog(ERROR, "could not initialize %s context", "SHA384");
+ if (pg_sha2_update(ctx, data, len) < 0)
+ elog(ERROR, "could not update %s context", "SHA384");
+ if (pg_sha2_final(ctx, buf) < 0)
+ elog(ERROR, "could not finalize %s context", "SHA384");
+ pg_sha2_free(ctx);
result = palloc(sizeof(buf) + VARHDRSZ);
SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
@@ -150,16 +165,21 @@ sha512_bytea(PG_FUNCTION_ARGS)
bytea *in = PG_GETARG_BYTEA_PP(0);
const uint8 *data;
size_t len;
- pg_sha512_ctx ctx;
+ pg_sha2_ctx *ctx;
unsigned char buf[PG_SHA512_DIGEST_LENGTH];
bytea *result;
len = VARSIZE_ANY_EXHDR(in);
data = (unsigned char *) VARDATA_ANY(in);
- pg_sha512_init(&ctx);
- pg_sha512_update(&ctx, data, len);
- pg_sha512_final(&ctx, buf);
+ ctx = pg_sha2_create(PG_SHA512);
+ if (pg_sha2_init(ctx) < 0)
+ elog(ERROR, "could not initialize %s context", "SHA512");
+ if (pg_sha2_update(ctx, data, len) < 0)
+ elog(ERROR, "could not update %s context", "SHA512");
+ if (pg_sha2_final(ctx, buf) < 0)
+ elog(ERROR, "could not finalize %s context", "SHA512");
+ pg_sha2_free(ctx);
result = palloc(sizeof(buf) + VARHDRSZ);
SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
diff --git a/src/common/checksum_helper.c b/src/common/checksum_helper.c
index 79a9a7447b..db50065a8a 100644
--- a/src/common/checksum_helper.c
+++ b/src/common/checksum_helper.c
@@ -77,8 +77,9 @@ pg_checksum_type_name(pg_checksum_type type)
/*
* Initialize a checksum context for checksums of the given type.
+ * Returns 0 for a success, -1 for a failure.
*/
-void
+int
pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
{
context->type = type;
@@ -92,24 +93,55 @@ pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
INIT_CRC32C(context->raw_context.c_crc32c);
break;
case CHECKSUM_TYPE_SHA224:
- pg_sha224_init(&context->raw_context.c_sha224);
+ context->raw_context.c_sha224 = pg_sha2_create(PG_SHA224);
+ if (context->raw_context.c_sha224 == NULL)
+ return -1;
+ if (pg_sha2_init(context->raw_context.c_sha224) < 0)
+ {
+ pg_sha2_free(context->raw_context.c_sha224);
+ return -1;
+ }
break;
case CHECKSUM_TYPE_SHA256:
- pg_sha256_init(&context->raw_context.c_sha256);
+ context->raw_context.c_sha256 = pg_sha2_create(PG_SHA256);
+ if (context->raw_context.c_sha256 == NULL)
+ return -1;
+ if (pg_sha2_init(context->raw_context.c_sha256) < 0)
+ {
+ pg_sha2_free(context->raw_context.c_sha256);
+ return -1;
+ }
break;
case CHECKSUM_TYPE_SHA384:
- pg_sha384_init(&context->raw_context.c_sha384);
+ context->raw_context.c_sha384 = pg_sha2_create(PG_SHA384);
+ if (context->raw_context.c_sha384 == NULL)
+ return -1;
+ if (pg_sha2_init(context->raw_context.c_sha384) < 0)
+ {
+ pg_sha2_free(context->raw_context.c_sha384);
+ return -1;
+ }
break;
case CHECKSUM_TYPE_SHA512:
- pg_sha512_init(&context->raw_context.c_sha512);
+ context->raw_context.c_sha512 = pg_sha2_create(PG_SHA512);
+ if (context->raw_context.c_sha512 == NULL)
+ return -1;
+ if (pg_sha2_init(context->raw_context.c_sha512) < 0)
+ {
+ pg_sha2_free(context->raw_context.c_sha512);
+ return -1;
+ }
break;
}
+
+ return 0;
}
/*
* Update a checksum context with new data.
+ * Returns 0 for a success, -1 for a failure.
*/
-void
+int
pg_checksum_update(pg_checksum_context *context, const uint8 *input,
size_t len)
{
@@ -122,25 +154,32 @@ pg_checksum_update(pg_checksum_context *context, const uint8 *input,
COMP_CRC32C(context->raw_context.c_crc32c, input, len);
break;
case CHECKSUM_TYPE_SHA224:
- pg_sha224_update(&context->raw_context.c_sha224, input, len);
+ if (pg_sha2_update(context->raw_context.c_sha224, input, len) < 0)
+ return -1;
break;
case CHECKSUM_TYPE_SHA256:
- pg_sha256_update(&context->raw_context.c_sha256, input, len);
+ if (pg_sha2_update(context->raw_context.c_sha256, input, len) < 0)
+ return -1;
break;
case CHECKSUM_TYPE_SHA384:
- pg_sha384_update(&context->raw_context.c_sha384, input, len);
+ if (pg_sha2_update(context->raw_context.c_sha384, input, len) < 0)
+ return -1;
break;
case CHECKSUM_TYPE_SHA512:
- pg_sha512_update(&context->raw_context.c_sha512, input, len);
+ if (pg_sha2_update(context->raw_context.c_sha512, input, len) < 0)
+ return -1;
break;
}
+
+ return 0;
}
/*
* Finalize a checksum computation and write the result to an output buffer.
*
* The caller must ensure that the buffer is at least PG_CHECKSUM_MAX_LENGTH
- * bytes in length. The return value is the number of bytes actually written.
+ * bytes in length. The return value is the number of bytes actually written,
+ * or -1 for a failure.
*/
int
pg_checksum_final(pg_checksum_context *context, uint8 *output)
@@ -168,19 +207,27 @@ pg_checksum_final(pg_checksum_context *context, uint8 *output)
memcpy(output, &context->raw_context.c_crc32c, retval);
break;
case CHECKSUM_TYPE_SHA224:
- pg_sha224_final(&context->raw_context.c_sha224, output);
+ if (pg_sha2_final(context->raw_context.c_sha224, output) < 0)
+ return -1;
+ pg_sha2_free(context->raw_context.c_sha224);
retval = PG_SHA224_DIGEST_LENGTH;
break;
case CHECKSUM_TYPE_SHA256:
- pg_sha256_final(&context->raw_context.c_sha256, output);
- retval = PG_SHA256_DIGEST_LENGTH;
+ if (pg_sha2_final(context->raw_context.c_sha256, output) < 0)
+ return -1;
+ pg_sha2_free(context->raw_context.c_sha256);
+ retval = PG_SHA224_DIGEST_LENGTH;
break;
case CHECKSUM_TYPE_SHA384:
- pg_sha384_final(&context->raw_context.c_sha384, output);
+ if (pg_sha2_final(context->raw_context.c_sha384, output) < 0)
+ return -1;
+ pg_sha2_free(context->raw_context.c_sha384);
retval = PG_SHA384_DIGEST_LENGTH;
break;
case CHECKSUM_TYPE_SHA512:
- pg_sha512_final(&context->raw_context.c_sha512, output);
+ if (pg_sha2_final(context->raw_context.c_sha512, output) < 0)
+ return -1;
+ pg_sha2_free(context->raw_context.c_sha512);
retval = PG_SHA512_DIGEST_LENGTH;
break;
}
diff --git a/src/common/scram-common.c b/src/common/scram-common.c
index 4971134b22..af2940eccf 100644
--- a/src/common/scram-common.c
+++ b/src/common/scram-common.c
@@ -13,6 +13,7 @@
*
*-------------------------------------------------------------------------
*/
+
#ifndef FRONTEND
#include "postgres.h"
#else
@@ -29,9 +30,9 @@
/*
* Calculate HMAC per RFC2104.
*
- * The hash function used is SHA-256.
+ * The hash function used is SHA-256. Returns 0 on success, -1 on failure.
*/
-void
+int
scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen)
{
uint8 k_ipad[SHA256_HMAC_B];
@@ -44,13 +45,21 @@ scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen)
*/
if (keylen > SHA256_HMAC_B)
{
- pg_sha256_ctx sha256_ctx;
+ pg_sha2_ctx *sha256_ctx;
- pg_sha256_init(&sha256_ctx);
- pg_sha256_update(&sha256_ctx, key, keylen);
- pg_sha256_final(&sha256_ctx, keybuf);
+ sha256_ctx = pg_sha2_create(PG_SHA256);
+ if (sha256_ctx == NULL)
+ return -1;
+ if (pg_sha2_init(sha256_ctx) < 0 ||
+ pg_sha2_update(sha256_ctx, key, keylen) < 0 ||
+ pg_sha2_final(sha256_ctx, keybuf) < 0)
+ {
+ pg_sha2_free(sha256_ctx);
+ return -1;
+ }
key = keybuf;
keylen = SCRAM_KEY_LEN;
+ pg_sha2_free(sha256_ctx);
}
memset(k_ipad, HMAC_IPAD, SHA256_HMAC_B);
@@ -62,45 +71,75 @@ scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen)
ctx->k_opad[i] ^= key[i];
}
+ ctx->sha256ctx = pg_sha2_create(PG_SHA256);
+ if (ctx->sha256ctx == NULL)
+ return -1;
+
/* tmp = H(K XOR ipad, text) */
- pg_sha256_init(&ctx->sha256ctx);
- pg_sha256_update(&ctx->sha256ctx, k_ipad, SHA256_HMAC_B);
+ if (pg_sha2_init(ctx->sha256ctx) < 0 ||
+ pg_sha2_update(ctx->sha256ctx, k_ipad, SHA256_HMAC_B) < 0)
+ {
+ pg_sha2_free(ctx->sha256ctx);
+ return -1;
+ }
+
+ return 0;
}
/*
* Update HMAC calculation
- * The hash function used is SHA-256.
+ * The hash function used is SHA-256. Returns 0 on success, -1 on failure.
*/
-void
+int
scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen)
{
- pg_sha256_update(&ctx->sha256ctx, (const uint8 *) str, slen);
+ Assert(ctx->sha256ctx != NULL);
+ if (pg_sha2_update(ctx->sha256ctx, (const uint8 *) str, slen) < 0)
+ {
+ pg_sha2_free(ctx->sha256ctx);
+ return -1;
+ }
+ return 0;
}
/*
* Finalize HMAC calculation.
- * The hash function used is SHA-256.
+ * The hash function used is SHA-256. Returns 0 on success, -1 on failure.
*/
-void
+int
scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx)
{
uint8 h[SCRAM_KEY_LEN];
- pg_sha256_final(&ctx->sha256ctx, h);
+ Assert(ctx->sha256ctx != NULL);
+
+ if (pg_sha2_final(ctx->sha256ctx, h) < 0)
+ {
+ pg_sha2_free(ctx->sha256ctx);
+ return -1;
+ }
/* H(K XOR opad, tmp) */
- pg_sha256_init(&ctx->sha256ctx);
- pg_sha256_update(&ctx->sha256ctx, ctx->k_opad, SHA256_HMAC_B);
- pg_sha256_update(&ctx->sha256ctx, h, SCRAM_KEY_LEN);
- pg_sha256_final(&ctx->sha256ctx, result);
+ if (pg_sha2_init(ctx->sha256ctx) < 0 ||
+ pg_sha2_update(ctx->sha256ctx, ctx->k_opad, SHA256_HMAC_B) < 0 ||
+ pg_sha2_update(ctx->sha256ctx, h, SCRAM_KEY_LEN) < 0 ||
+ pg_sha2_final(ctx->sha256ctx, result) < 0)
+ {
+ pg_sha2_free(ctx->sha256ctx);
+ return -1;
+ }
+
+ pg_sha2_free(ctx->sha256ctx);
+ return 0;
}
/*
* Calculate SaltedPassword.
*
- * The password should already be normalized by SASLprep.
+ * The password should already be normalized by SASLprep. Returns 0 on
+ * success, -1 on failure.
*/
-void
+int
scram_SaltedPassword(const char *password,
const char *salt, int saltlen, int iterations,
uint8 *result)
@@ -120,63 +159,86 @@ scram_SaltedPassword(const char *password,
*/
/* First iteration */
- scram_HMAC_init(&hmac_ctx, (uint8 *) password, password_len);
- scram_HMAC_update(&hmac_ctx, salt, saltlen);
- scram_HMAC_update(&hmac_ctx, (char *) &one, sizeof(uint32));
- scram_HMAC_final(Ui_prev, &hmac_ctx);
+ 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)
+ return -1;
+
memcpy(result, Ui_prev, SCRAM_KEY_LEN);
/* Subsequent iterations */
for (i = 2; i <= iterations; i++)
{
- scram_HMAC_init(&hmac_ctx, (uint8 *) password, password_len);
- scram_HMAC_update(&hmac_ctx, (const char *) Ui_prev, SCRAM_KEY_LEN);
- scram_HMAC_final(Ui, &hmac_ctx);
+ 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)
+ return -1;
+
for (j = 0; j < SCRAM_KEY_LEN; j++)
result[j] ^= Ui[j];
memcpy(Ui_prev, Ui, SCRAM_KEY_LEN);
}
+
+ return 0;
}
/*
* Calculate SHA-256 hash for a NULL-terminated string. (The NULL terminator is
- * not included in the hash).
+ * not included in the hash). Returns 0 on success, -1 on failure.
*/
-void
+int
scram_H(const uint8 *input, int len, uint8 *result)
{
- pg_sha256_ctx ctx;
+ pg_sha2_ctx *ctx;
- pg_sha256_init(&ctx);
- pg_sha256_update(&ctx, input, len);
- pg_sha256_final(&ctx, result);
+ ctx = pg_sha2_create(PG_SHA256);
+ if (ctx == NULL)
+ return -1;
+
+ if (pg_sha2_init(ctx) < 0 ||
+ pg_sha2_update(ctx, input, len) < 0 ||
+ pg_sha2_final(ctx, result) < 0)
+ {
+ pg_sha2_free(ctx);
+ return -1;
+ }
+
+ pg_sha2_free(ctx);
+ return 0;
}
/*
- * Calculate ClientKey.
+ * Calculate ClientKey. Returns 0 on success, -1 on failure.
*/
-void
+int
scram_ClientKey(const uint8 *salted_password, uint8 *result)
{
scram_HMAC_ctx ctx;
- scram_HMAC_init(&ctx, salted_password, SCRAM_KEY_LEN);
- scram_HMAC_update(&ctx, "Client Key", strlen("Client Key"));
- scram_HMAC_final(result, &ctx);
+ 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)
+ return -1;
+
+ return 0;
}
/*
- * Calculate ServerKey.
+ * Calculate ServerKey. Returns 0 on success, -1 on failure.
*/
-void
+int
scram_ServerKey(const uint8 *salted_password, uint8 *result)
{
scram_HMAC_ctx ctx;
- scram_HMAC_init(&ctx, salted_password, SCRAM_KEY_LEN);
- scram_HMAC_update(&ctx, "Server Key", strlen("Server Key"));
- scram_HMAC_final(result, &ctx);
+ 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)
+ return -1;
+
+ return 0;
}
@@ -207,12 +269,18 @@ scram_build_secret(const char *salt, int saltlen, int iterations,
iterations = SCRAM_DEFAULT_ITERATIONS;
/* Calculate StoredKey and ServerKey */
- scram_SaltedPassword(password, salt, saltlen, iterations,
- salted_password);
- scram_ClientKey(salted_password, stored_key);
- scram_H(stored_key, SCRAM_KEY_LEN, stored_key);
-
- scram_ServerKey(salted_password, server_key);
+ if (scram_SaltedPassword(password, salt, saltlen, iterations,
+ salted_password) < 0 ||
+ scram_ClientKey(salted_password, stored_key) < 0 ||
+ scram_H(stored_key, SCRAM_KEY_LEN, stored_key) < 0 ||
+ scram_ServerKey(salted_password, server_key) < 0)
+ {
+#ifdef FRONTEND
+ return NULL;
+#else
+ elog(ERROR, "could not calculate stored key and server key");
+#endif
+ }
/*----------
* The format is:
diff --git a/src/common/sha2.c b/src/common/sha2.c
index 0d329bb238..5a0dfd7f8d 100644
--- a/src/common/sha2.c
+++ b/src/common/sha2.c
@@ -60,6 +60,34 @@
#include "common/sha2.h"
+/* Internal structures used for the private area of pg_sha2_ctx->data */
+typedef struct pg_sha256_ctx
+{
+ uint32 state[8];
+ uint64 bitcount;
+ uint8 buffer[PG_SHA256_BLOCK_LENGTH];
+} pg_sha256_ctx;
+typedef struct pg_sha512_ctx
+{
+ uint64 state[8];
+ uint64 bitcount[2];
+ uint8 buffer[PG_SHA512_BLOCK_LENGTH];
+} pg_sha512_ctx;
+typedef struct pg_sha256_ctx pg_sha224_ctx;
+typedef struct pg_sha512_ctx pg_sha384_ctx;
+
+/*
+ * In backend, use palloc/pfree to ease the error handling. In frontend,
+ * use malloc to be able to return a failure status back to the caller.
+ */
+#ifndef FRONTEND
+#define ALLOC(size) palloc(size)
+#define FREE(ptr) pfree(ptr)
+#else
+#define ALLOC(size) malloc(size)
+#define FREE(ptr) free(ptr)
+#endif
+
/*
* UNROLLED TRANSFORM LOOP NOTE:
* You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
@@ -264,7 +292,7 @@ static const uint64 sha512_initial_hash_value[8] = {
/*** SHA-256: *********************************************************/
-void
+static void
pg_sha256_init(pg_sha256_ctx *context)
{
if (context == NULL)
@@ -461,7 +489,7 @@ SHA256_Transform(pg_sha256_ctx *context, const uint8 *data)
}
#endif /* SHA2_UNROLL_TRANSFORM */
-void
+static void
pg_sha256_update(pg_sha256_ctx *context, const uint8 *data, size_t len)
{
size_t freespace,
@@ -562,7 +590,7 @@ SHA256_Last(pg_sha256_ctx *context)
SHA256_Transform(context, context->buffer);
}
-void
+static void
pg_sha256_final(pg_sha256_ctx *context, uint8 *digest)
{
/* If no digest buffer is passed, we don't bother doing this: */
@@ -590,7 +618,7 @@ pg_sha256_final(pg_sha256_ctx *context, uint8 *digest)
/*** SHA-512: *********************************************************/
-void
+static void
pg_sha512_init(pg_sha512_ctx *context)
{
if (context == NULL)
@@ -787,7 +815,7 @@ SHA512_Transform(pg_sha512_ctx *context, const uint8 *data)
}
#endif /* SHA2_UNROLL_TRANSFORM */
-void
+static void
pg_sha512_update(pg_sha512_ctx *context, const uint8 *data, size_t len)
{
size_t freespace,
@@ -890,7 +918,7 @@ SHA512_Last(pg_sha512_ctx *context)
SHA512_Transform(context, context->buffer);
}
-void
+static void
pg_sha512_final(pg_sha512_ctx *context, uint8 *digest)
{
/* If no digest buffer is passed, we don't bother doing this: */
@@ -919,7 +947,7 @@ pg_sha512_final(pg_sha512_ctx *context, uint8 *digest)
/*** SHA-384: *********************************************************/
-void
+static void
pg_sha384_init(pg_sha384_ctx *context)
{
if (context == NULL)
@@ -929,13 +957,13 @@ pg_sha384_init(pg_sha384_ctx *context)
context->bitcount[0] = context->bitcount[1] = 0;
}
-void
+static void
pg_sha384_update(pg_sha384_ctx *context, const uint8 *data, size_t len)
{
pg_sha512_update((pg_sha512_ctx *) context, data, len);
}
-void
+static void
pg_sha384_final(pg_sha384_ctx *context, uint8 *digest)
{
/* If no digest buffer is passed, we don't bother doing this: */
@@ -963,7 +991,7 @@ pg_sha384_final(pg_sha384_ctx *context, uint8 *digest)
}
/*** SHA-224: *********************************************************/
-void
+static void
pg_sha224_init(pg_sha224_ctx *context)
{
if (context == NULL)
@@ -973,13 +1001,13 @@ pg_sha224_init(pg_sha224_ctx *context)
context->bitcount = 0;
}
-void
+static void
pg_sha224_update(pg_sha224_ctx *context, const uint8 *data, size_t len)
{
pg_sha256_update((pg_sha256_ctx *) context, data, len);
}
-void
+static void
pg_sha224_final(pg_sha224_ctx *context, uint8 *digest)
{
/* If no digest buffer is passed, we don't bother doing this: */
@@ -1004,3 +1032,155 @@ pg_sha224_final(pg_sha224_ctx *context, uint8 *digest)
/* Clean up state data: */
memset(context, 0, sizeof(pg_sha224_ctx));
}
+
+/* External routines for this set of SHA2 implementations */
+
+/*
+ * pg_sha2_create
+ *
+ * Allocate a SHA2 context. Returns NULL on failure.
+ */
+pg_sha2_ctx *
+pg_sha2_create(pg_sha2_type type)
+{
+ pg_sha2_ctx *ctx;
+
+ ctx = ALLOC(sizeof(pg_sha2_ctx));
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->type = type;
+
+ switch (type)
+ {
+ case PG_SHA224:
+ ctx->data = ALLOC(sizeof(pg_sha224_ctx));
+ break;
+ case PG_SHA256:
+ ctx->data = ALLOC(sizeof(pg_sha256_ctx));
+ break;
+ case PG_SHA384:
+ ctx->data = ALLOC(sizeof(pg_sha384_ctx));
+ break;
+ case PG_SHA512:
+ ctx->data = ALLOC(sizeof(pg_sha512_ctx));
+ break;
+ }
+
+ if (ctx->data == NULL)
+ {
+ explicit_bzero(ctx, sizeof(pg_sha2_ctx));
+ FREE(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+/*
+ * pg_sha2_init
+ *
+ * Initialize a SHA2 context. Note that this implementation is designed
+ * to never fail, so this always returns 0.
+ */
+int
+pg_sha2_init(pg_sha2_ctx *ctx)
+{
+ if (ctx == NULL)
+ return 0;
+
+ switch (ctx->type)
+ {
+ case PG_SHA224:
+ pg_sha224_init((pg_sha224_ctx *) ctx->data);
+ break;
+ case PG_SHA256:
+ pg_sha256_init((pg_sha256_ctx *) ctx->data);
+ break;
+ case PG_SHA384:
+ pg_sha384_init((pg_sha384_ctx *) ctx->data);
+ break;
+ case PG_SHA512:
+ pg_sha512_init((pg_sha512_ctx *) ctx->data);
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * pg_sha2_update
+ *
+ * Update a SHA2 context. Note that this implementation is designed
+ * to never fail, so this always returns 0.
+ */
+int
+pg_sha2_update(pg_sha2_ctx *ctx, const uint8 *data, size_t len)
+{
+ if (ctx == NULL)
+ return 0;
+
+ switch (ctx->type)
+ {
+ case PG_SHA224:
+ pg_sha224_update((pg_sha224_ctx *) ctx->data, data, len);
+ break;
+ case PG_SHA256:
+ pg_sha256_update((pg_sha256_ctx *) ctx->data, data, len);
+ break;
+ case PG_SHA384:
+ pg_sha384_update((pg_sha384_ctx *) ctx->data, data, len);
+ break;
+ case PG_SHA512:
+ pg_sha512_update((pg_sha512_ctx *) ctx->data, data, len);
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * pg_sha2_final
+ *
+ * Finalize a SHA2 context. Note that this implementation is designed
+ * to never fail, so this always returns 0.
+ */
+int
+pg_sha2_final(pg_sha2_ctx *ctx, uint8 *dest)
+{
+ if (ctx == NULL)
+ return 0;
+
+ switch (ctx->type)
+ {
+ case PG_SHA224:
+ pg_sha224_final((pg_sha224_ctx *) ctx->data, dest);
+ break;
+ case PG_SHA256:
+ pg_sha256_final((pg_sha256_ctx *) ctx->data, dest);
+ break;
+ case PG_SHA384:
+ pg_sha384_final((pg_sha384_ctx *) ctx->data, dest);
+ break;
+ case PG_SHA512:
+ pg_sha512_final((pg_sha512_ctx *) ctx->data, dest);
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * pg_sha2_free
+ *
+ * Free a SHA2 context.
+ */
+void
+pg_sha2_free(pg_sha2_ctx *ctx)
+{
+ if (ctx == NULL)
+ return;
+ FREE(ctx->data);
+ explicit_bzero(ctx, sizeof(pg_sha2_ctx));
+ FREE(ctx);
+}
diff --git a/src/common/sha2_openssl.c b/src/common/sha2_openssl.c
index 41673b3a88..57de96df90 100644
--- a/src/common/sha2_openssl.c
+++ b/src/common/sha2_openssl.c
@@ -24,79 +24,172 @@
#include "common/sha2.h"
+/*
+ * In backend, use palloc/pfree to ease the error handling. In frontend,
+ * use malloc to be able to return a failure status back to the caller.
+ */
+#ifndef FRONTEND
+#define ALLOC(size) palloc(size)
+#define FREE(ptr) pfree(ptr)
+#else
+#define ALLOC(size) malloc(size)
+#define FREE(ptr) free(ptr)
+#endif
-/* Interface routines for SHA-256 */
-void
-pg_sha256_init(pg_sha256_ctx *ctx)
+/*
+ * pg_sha2_create
+ *
+ * Allocate a SHA2 context. Returns NULL on failure.
+ */
+pg_sha2_ctx *
+pg_sha2_create(pg_sha2_type type)
{
- SHA256_Init((SHA256_CTX *) ctx);
+ pg_sha2_ctx *ctx;
+
+ ctx = ALLOC(sizeof(pg_sha2_ctx));
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->type = type;
+
+ switch (type)
+ {
+ 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;
+ }
+
+ if (ctx->data == NULL)
+ {
+ explicit_bzero(ctx, sizeof(pg_sha2_ctx));
+ FREE(ctx);
+ return NULL;
+ }
+
+ return ctx;
}
-void
-pg_sha256_update(pg_sha256_ctx *ctx, const uint8 *data, size_t len)
+/*
+ * pg_sha2_init
+ *
+ * Initialize a SHA2 context. Returns 0 on success, and -1 on failure.
+ */
+int
+pg_sha2_init(pg_sha2_ctx *ctx)
{
- SHA256_Update((SHA256_CTX *) ctx, data, len);
+ int status = 0;
+
+ if (ctx == NULL)
+ return 0;
+
+ switch (ctx->type)
+ {
+ case PG_SHA224:
+ status = SHA224_Init((SHA256_CTX *) ctx->data);
+ break;
+ case PG_SHA256:
+ status = SHA256_Init((SHA256_CTX *) ctx->data);
+ break;
+ case PG_SHA384:
+ status = SHA384_Init((SHA512_CTX *) ctx->data);
+ break;
+ case PG_SHA512:
+ status = SHA512_Init((SHA512_CTX *) ctx->data);
+ break;
+ }
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ return -1;
+ return 0;
}
-void
-pg_sha256_final(pg_sha256_ctx *ctx, uint8 *dest)
+/*
+ * pg_sha2_update
+ *
+ * Update a SHA2 context. Returns 0 on success, and -1 on failure.
+ */
+int
+pg_sha2_update(pg_sha2_ctx *ctx, const uint8 *data, size_t len)
{
- SHA256_Final(dest, (SHA256_CTX *) ctx);
+ int status;
+
+ 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;
+ }
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ return -1;
+ return 0;
}
-/* Interface routines for SHA-512 */
-void
-pg_sha512_init(pg_sha512_ctx *ctx)
+/*
+ * pg_sha2_final
+ *
+ * Finalize a SHA2 context. Returns 0 on success, and -1 on failure.
+ */
+int
+pg_sha2_final(pg_sha2_ctx *ctx, uint8 *dest)
{
- SHA512_Init((SHA512_CTX *) ctx);
+ int status;
+
+ 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;
+ }
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ return -1;
+ return 0;
}
+/*
+ * pg_sha2_free
+ *
+ * Free a SHA2 context.
+ */
void
-pg_sha512_update(pg_sha512_ctx *ctx, const uint8 *data, size_t len)
+pg_sha2_free(pg_sha2_ctx *ctx)
{
- SHA512_Update((SHA512_CTX *) ctx, data, len);
-}
-
-void
-pg_sha512_final(pg_sha512_ctx *ctx, uint8 *dest)
-{
- SHA512_Final(dest, (SHA512_CTX *) ctx);
-}
-
-/* Interface routines for SHA-384 */
-void
-pg_sha384_init(pg_sha384_ctx *ctx)
-{
- SHA384_Init((SHA512_CTX *) ctx);
-}
-
-void
-pg_sha384_update(pg_sha384_ctx *ctx, const uint8 *data, size_t len)
-{
- SHA384_Update((SHA512_CTX *) ctx, data, len);
-}
-
-void
-pg_sha384_final(pg_sha384_ctx *ctx, uint8 *dest)
-{
- SHA384_Final(dest, (SHA512_CTX *) ctx);
-}
-
-/* Interface routines for SHA-224 */
-void
-pg_sha224_init(pg_sha224_ctx *ctx)
-{
- SHA224_Init((SHA256_CTX *) ctx);
-}
-
-void
-pg_sha224_update(pg_sha224_ctx *ctx, const uint8 *data, size_t len)
-{
- SHA224_Update((SHA256_CTX *) ctx, data, len);
-}
-
-void
-pg_sha224_final(pg_sha224_ctx *ctx, uint8 *dest)
-{
- SHA224_Final(dest, (SHA256_CTX *) ctx);
+ if (ctx == NULL)
+ return;
+ FREE(ctx->data);
+ explicit_bzero(ctx, sizeof(pg_sha2_ctx));
+ FREE(ctx);
}
diff --git a/src/bin/pg_verifybackup/parse_manifest.c b/src/bin/pg_verifybackup/parse_manifest.c
index 608e23538b..e3e4f54ea9 100644
--- a/src/bin/pg_verifybackup/parse_manifest.c
+++ b/src/bin/pg_verifybackup/parse_manifest.c
@@ -624,7 +624,7 @@ verify_manifest_checksum(JsonManifestParseState *parse, char *buffer,
size_t number_of_newlines = 0;
size_t ultimate_newline = 0;
size_t penultimate_newline = 0;
- pg_sha256_ctx manifest_ctx;
+ pg_sha2_ctx *manifest_ctx;
uint8 manifest_checksum_actual[PG_SHA256_DIGEST_LENGTH];
uint8 manifest_checksum_expected[PG_SHA256_DIGEST_LENGTH];
@@ -652,9 +652,15 @@ verify_manifest_checksum(JsonManifestParseState *parse, char *buffer,
"last line not newline-terminated");
/* Checksum the rest. */
- pg_sha256_init(&manifest_ctx);
- pg_sha256_update(&manifest_ctx, (uint8 *) buffer, penultimate_newline + 1);
- pg_sha256_final(&manifest_ctx, manifest_checksum_actual);
+ manifest_ctx = pg_sha2_create(PG_SHA256);
+ if (manifest_ctx == NULL)
+ context->error_cb(context, "out of memory");
+ if (pg_sha2_init(manifest_ctx) < 0)
+ context->error_cb(context, "could not initialize checksum of manifest");
+ if (pg_sha2_update(manifest_ctx, (uint8 *) buffer, penultimate_newline + 1) < 0)
+ context->error_cb(context, "could not update checksum of manifest");
+ if (pg_sha2_final(manifest_ctx, manifest_checksum_actual) < 0)
+ context->error_cb(context, "could not finalize checksum of manifest");
/* Now verify it. */
if (parse->manifest_checksum == NULL)
@@ -667,6 +673,7 @@ verify_manifest_checksum(JsonManifestParseState *parse, char *buffer,
if (memcmp(manifest_checksum_actual, manifest_checksum_expected,
PG_SHA256_DIGEST_LENGTH) != 0)
context->error_cb(context, "manifest checksum mismatch");
+ pg_sha2_free(manifest_ctx);
}
/*
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c
index bb3733b57e..07320d3699 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -726,13 +726,26 @@ verify_file_checksum(verifier_context *context, manifest_file *m,
}
/* Initialize checksum context. */
- pg_checksum_init(&checksum_ctx, m->checksum_type);
+ if (pg_checksum_init(&checksum_ctx, m->checksum_type) < 0)
+ {
+ report_backup_error(context, "could not initialize checksum of file \"%s\"",
+ relpath);
+ return;
+ }
/* Read the file chunk by chunk, updating the checksum as we go. */
while ((rc = read(fd, buffer, READ_CHUNK_SIZE)) > 0)
{
bytes_read += rc;
- pg_checksum_update(&checksum_ctx, buffer, rc);
+ if (pg_checksum_update(&checksum_ctx, buffer, rc) < 0)
+ {
+ report_backup_error(context, "could not update checksum of file \"%s\"",
+ relpath);
+ close(fd);
+ return;
+ }
+
+
}
if (rc < 0)
report_backup_error(context, "could not read file \"%s\": %m",
@@ -767,6 +780,13 @@ verify_file_checksum(verifier_context *context, manifest_file *m,
/* Get the final checksum. */
checksumlen = pg_checksum_final(&checksum_ctx, checksumbuf);
+ if (checksumlen < 0)
+ {
+ report_backup_error(context,
+ "could not finalize checksum of file \"%s\"",
+ relpath);
+ return;
+ }
/* And check it against the manifest. */
if (checksumlen != m->checksum_length)
diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c
index 6d266e9796..0a216cbe84 100644
--- a/src/interfaces/libpq/fe-auth-scram.c
+++ b/src/interfaces/libpq/fe-auth-scram.c
@@ -63,8 +63,8 @@ static bool read_server_first_message(fe_scram_state *state, char *input);
static bool read_server_final_message(fe_scram_state *state, char *input);
static char *build_client_first_message(fe_scram_state *state);
static char *build_client_final_message(fe_scram_state *state);
-static bool verify_server_signature(fe_scram_state *state);
-static void calculate_client_proof(fe_scram_state *state,
+static bool verify_server_signature(fe_scram_state *state, bool *match);
+static bool calculate_client_proof(fe_scram_state *state,
const char *client_final_message_without_proof,
uint8 *result);
@@ -256,11 +256,15 @@ pg_fe_scram_exchange(void *opaq, char *input, int inputlen,
* Verify server signature, to make sure we're talking to the
* genuine server.
*/
- if (verify_server_signature(state))
- *success = true;
- else
+ if (!verify_server_signature(state, success))
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not verify server signature\n"));
+ goto error;
+ }
+
+ if (!*success)
{
- *success = false;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("incorrect server signature\n"));
}
@@ -544,9 +548,15 @@ build_client_final_message(fe_scram_state *state)
goto oom_error;
/* Append proof to it, to form client-final-message. */
- calculate_client_proof(state,
- state->client_final_message_without_proof,
- client_proof);
+ if (!calculate_client_proof(state,
+ state->client_final_message_without_proof,
+ client_proof))
+ {
+ termPQExpBuffer(&buf);
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not calculate client proof\n"));
+ return NULL;
+ }
appendPQExpBufferStr(&buf, ",p=");
encoded_len = pg_b64_enc_len(SCRAM_KEY_LEN);
@@ -745,9 +755,9 @@ read_server_final_message(fe_scram_state *state, char *input)
/*
* Calculate the client proof, part of the final exchange message sent
- * by the client.
+ * by the client. Returns true on success, false on failure.
*/
-static void
+static bool
calculate_client_proof(fe_scram_state *state,
const char *client_final_message_without_proof,
uint8 *result)
@@ -762,61 +772,67 @@ calculate_client_proof(fe_scram_state *state,
* Calculate SaltedPassword, and store it in 'state' so that we can reuse
* it later in verify_server_signature.
*/
- scram_SaltedPassword(state->password, state->salt, state->saltlen,
- state->iterations, state->SaltedPassword);
-
- scram_ClientKey(state->SaltedPassword, ClientKey);
- scram_H(ClientKey, SCRAM_KEY_LEN, StoredKey);
-
- scram_HMAC_init(&ctx, StoredKey, SCRAM_KEY_LEN);
- scram_HMAC_update(&ctx,
- state->client_first_message_bare,
- strlen(state->client_first_message_bare));
- scram_HMAC_update(&ctx, ",", 1);
- scram_HMAC_update(&ctx,
- state->server_first_message,
- strlen(state->server_first_message));
- scram_HMAC_update(&ctx, ",", 1);
- scram_HMAC_update(&ctx,
- client_final_message_without_proof,
- strlen(client_final_message_without_proof));
- scram_HMAC_final(ClientSignature, &ctx);
+ if (scram_SaltedPassword(state->password, state->salt, state->saltlen,
+ state->iterations, state->SaltedPassword) < 0 ||
+ scram_ClientKey(state->SaltedPassword, ClientKey) < 0 ||
+ scram_H(ClientKey, SCRAM_KEY_LEN, StoredKey) < 0 ||
+ scram_HMAC_init(&ctx, StoredKey, SCRAM_KEY_LEN) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ scram_HMAC_update(&ctx, ",", 1) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ scram_HMAC_update(&ctx, ",", 1) < 0 ||
+ scram_HMAC_update(&ctx,
+ client_final_message_without_proof,
+ strlen(client_final_message_without_proof)) < 0 ||
+ scram_HMAC_final(ClientSignature, &ctx) < 0)
+ return false;
for (i = 0; i < SCRAM_KEY_LEN; i++)
result[i] = ClientKey[i] ^ ClientSignature[i];
+
+ return true;
}
/*
* Validate the server signature, received as part of the final exchange
- * message received from the server.
+ * message received from the server. *match tracks if the server signature
+ * matched or not. Returns true if the server signature got verified, and
+ * false for a processing error.
*/
static bool
-verify_server_signature(fe_scram_state *state)
+verify_server_signature(fe_scram_state *state, bool *match)
{
uint8 expected_ServerSignature[SCRAM_KEY_LEN];
uint8 ServerKey[SCRAM_KEY_LEN];
scram_HMAC_ctx ctx;
- scram_ServerKey(state->SaltedPassword, ServerKey);
-
+ if (scram_ServerKey(state->SaltedPassword, ServerKey) < 0 ||
/* calculate ServerSignature */
- scram_HMAC_init(&ctx, ServerKey, SCRAM_KEY_LEN);
- scram_HMAC_update(&ctx,
- state->client_first_message_bare,
- strlen(state->client_first_message_bare));
- scram_HMAC_update(&ctx, ",", 1);
- scram_HMAC_update(&ctx,
- state->server_first_message,
- strlen(state->server_first_message));
- scram_HMAC_update(&ctx, ",", 1);
- scram_HMAC_update(&ctx,
- state->client_final_message_without_proof,
- strlen(state->client_final_message_without_proof));
- scram_HMAC_final(expected_ServerSignature, &ctx);
-
- if (memcmp(expected_ServerSignature, state->ServerSignature, SCRAM_KEY_LEN) != 0)
+ scram_HMAC_init(&ctx, ServerKey, SCRAM_KEY_LEN) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ scram_HMAC_update(&ctx, ",", 1) < 0 ||
+ scram_HMAC_update(&ctx,
+ state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ scram_HMAC_update(&ctx, ",", 1) < 0 ||
+ 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)
return false;
+ /* signature processed, so now check after it */
+ if (memcmp(expected_ServerSignature, state->ServerSignature, SCRAM_KEY_LEN) != 0)
+ *match = false;
+ else
+ *match = true;
+
return true;
}
diff --git a/contrib/pgcrypto/internal-sha2.c b/contrib/pgcrypto/internal-sha2.c
index 9fa940b5bb..9037dfa4a6 100644
--- a/contrib/pgcrypto/internal-sha2.c
+++ b/contrib/pgcrypto/internal-sha2.c
@@ -42,7 +42,6 @@ void init_sha384(PX_MD *h);
void init_sha512(PX_MD *h);
/* SHA224 */
-
static unsigned
int_sha224_len(PX_MD *h)
{
@@ -55,42 +54,7 @@ int_sha224_block_len(PX_MD *h)
return PG_SHA224_BLOCK_LENGTH;
}
-static void
-int_sha224_update(PX_MD *h, const uint8 *data, unsigned dlen)
-{
- pg_sha224_ctx *ctx = (pg_sha224_ctx *) h->p.ptr;
-
- pg_sha224_update(ctx, data, dlen);
-}
-
-static void
-int_sha224_reset(PX_MD *h)
-{
- pg_sha224_ctx *ctx = (pg_sha224_ctx *) h->p.ptr;
-
- pg_sha224_init(ctx);
-}
-
-static void
-int_sha224_finish(PX_MD *h, uint8 *dst)
-{
- pg_sha224_ctx *ctx = (pg_sha224_ctx *) h->p.ptr;
-
- pg_sha224_final(ctx, dst);
-}
-
-static void
-int_sha224_free(PX_MD *h)
-{
- pg_sha224_ctx *ctx = (pg_sha224_ctx *) h->p.ptr;
-
- px_memset(ctx, 0, sizeof(*ctx));
- pfree(ctx);
- pfree(h);
-}
-
/* SHA256 */
-
static unsigned
int_sha256_len(PX_MD *h)
{
@@ -103,42 +67,7 @@ int_sha256_block_len(PX_MD *h)
return PG_SHA256_BLOCK_LENGTH;
}
-static void
-int_sha256_update(PX_MD *h, const uint8 *data, unsigned dlen)
-{
- pg_sha256_ctx *ctx = (pg_sha256_ctx *) h->p.ptr;
-
- pg_sha256_update(ctx, data, dlen);
-}
-
-static void
-int_sha256_reset(PX_MD *h)
-{
- pg_sha256_ctx *ctx = (pg_sha256_ctx *) h->p.ptr;
-
- pg_sha256_init(ctx);
-}
-
-static void
-int_sha256_finish(PX_MD *h, uint8 *dst)
-{
- pg_sha256_ctx *ctx = (pg_sha256_ctx *) h->p.ptr;
-
- pg_sha256_final(ctx, dst);
-}
-
-static void
-int_sha256_free(PX_MD *h)
-{
- pg_sha256_ctx *ctx = (pg_sha256_ctx *) h->p.ptr;
-
- px_memset(ctx, 0, sizeof(*ctx));
- pfree(ctx);
- pfree(h);
-}
-
/* SHA384 */
-
static unsigned
int_sha384_len(PX_MD *h)
{
@@ -151,42 +80,7 @@ int_sha384_block_len(PX_MD *h)
return PG_SHA384_BLOCK_LENGTH;
}
-static void
-int_sha384_update(PX_MD *h, const uint8 *data, unsigned dlen)
-{
- pg_sha384_ctx *ctx = (pg_sha384_ctx *) h->p.ptr;
-
- pg_sha384_update(ctx, data, dlen);
-}
-
-static void
-int_sha384_reset(PX_MD *h)
-{
- pg_sha384_ctx *ctx = (pg_sha384_ctx *) h->p.ptr;
-
- pg_sha384_init(ctx);
-}
-
-static void
-int_sha384_finish(PX_MD *h, uint8 *dst)
-{
- pg_sha384_ctx *ctx = (pg_sha384_ctx *) h->p.ptr;
-
- pg_sha384_final(ctx, dst);
-}
-
-static void
-int_sha384_free(PX_MD *h)
-{
- pg_sha384_ctx *ctx = (pg_sha384_ctx *) h->p.ptr;
-
- px_memset(ctx, 0, sizeof(*ctx));
- pfree(ctx);
- pfree(h);
-}
-
/* SHA512 */
-
static unsigned
int_sha512_len(PX_MD *h)
{
@@ -199,37 +93,40 @@ int_sha512_block_len(PX_MD *h)
return PG_SHA512_BLOCK_LENGTH;
}
+/* Generic interface for all SHA2 methods */
static void
-int_sha512_update(PX_MD *h, const uint8 *data, unsigned dlen)
+int_sha2_update(PX_MD *h, const uint8 *data, unsigned dlen)
{
- pg_sha512_ctx *ctx = (pg_sha512_ctx *) h->p.ptr;
+ pg_sha2_ctx *ctx = (pg_sha2_ctx *) h->p.ptr;
- pg_sha512_update(ctx, data, dlen);
+ if (pg_sha2_update(ctx, data, dlen) < 0)
+ elog(ERROR, "could not update %s context", "SHA2");
}
static void
-int_sha512_reset(PX_MD *h)
+int_sha2_reset(PX_MD *h)
{
- pg_sha512_ctx *ctx = (pg_sha512_ctx *) h->p.ptr;
+ pg_sha2_ctx *ctx = (pg_sha2_ctx *) h->p.ptr;
- pg_sha512_init(ctx);
+ if (pg_sha2_init(ctx) < 0)
+ elog(ERROR, "could not initialize %s context", "SHA2");
}
static void
-int_sha512_finish(PX_MD *h, uint8 *dst)
+int_sha2_finish(PX_MD *h, uint8 *dst)
{
- pg_sha512_ctx *ctx = (pg_sha512_ctx *) h->p.ptr;
+ pg_sha2_ctx *ctx = (pg_sha2_ctx *) h->p.ptr;
- pg_sha512_final(ctx, dst);
+ if (pg_sha2_final(ctx, dst) < 0)
+ elog(ERROR, "could not finalize %s context", "SHA2");
}
static void
-int_sha512_free(PX_MD *h)
+int_sha2_free(PX_MD *h)
{
- pg_sha512_ctx *ctx = (pg_sha512_ctx *) h->p.ptr;
+ pg_sha2_ctx *ctx = (pg_sha2_ctx *) h->p.ptr;
- px_memset(ctx, 0, sizeof(*ctx));
- pfree(ctx);
+ pg_sha2_free(ctx);
pfree(h);
}
@@ -238,18 +135,17 @@ int_sha512_free(PX_MD *h)
void
init_sha224(PX_MD *md)
{
- pg_sha224_ctx *ctx;
-
- ctx = palloc0(sizeof(*ctx));
+ pg_sha2_ctx *ctx;
+ ctx = pg_sha2_create(PG_SHA224);
md->p.ptr = ctx;
md->result_size = int_sha224_len;
md->block_size = int_sha224_block_len;
- md->reset = int_sha224_reset;
- md->update = int_sha224_update;
- md->finish = int_sha224_finish;
- md->free = int_sha224_free;
+ md->reset = int_sha2_reset;
+ md->update = int_sha2_update;
+ md->finish = int_sha2_finish;
+ md->free = int_sha2_free;
md->reset(md);
}
@@ -257,18 +153,17 @@ init_sha224(PX_MD *md)
void
init_sha256(PX_MD *md)
{
- pg_sha256_ctx *ctx;
-
- ctx = palloc0(sizeof(*ctx));
+ pg_sha2_ctx *ctx;
+ ctx = pg_sha2_create(PG_SHA256);
md->p.ptr = ctx;
md->result_size = int_sha256_len;
md->block_size = int_sha256_block_len;
- md->reset = int_sha256_reset;
- md->update = int_sha256_update;
- md->finish = int_sha256_finish;
- md->free = int_sha256_free;
+ md->reset = int_sha2_reset;
+ md->update = int_sha2_update;
+ md->finish = int_sha2_finish;
+ md->free = int_sha2_free;
md->reset(md);
}
@@ -276,18 +171,17 @@ init_sha256(PX_MD *md)
void
init_sha384(PX_MD *md)
{
- pg_sha384_ctx *ctx;
-
- ctx = palloc0(sizeof(*ctx));
+ pg_sha2_ctx *ctx;
+ ctx = pg_sha2_create(PG_SHA384);
md->p.ptr = ctx;
md->result_size = int_sha384_len;
md->block_size = int_sha384_block_len;
- md->reset = int_sha384_reset;
- md->update = int_sha384_update;
- md->finish = int_sha384_finish;
- md->free = int_sha384_free;
+ md->reset = int_sha2_reset;
+ md->update = int_sha2_update;
+ md->finish = int_sha2_finish;
+ md->free = int_sha2_free;
md->reset(md);
}
@@ -295,18 +189,17 @@ init_sha384(PX_MD *md)
void
init_sha512(PX_MD *md)
{
- pg_sha512_ctx *ctx;
-
- ctx = palloc0(sizeof(*ctx));
+ pg_sha2_ctx *ctx;
+ ctx = pg_sha2_create(PG_SHA512);
md->p.ptr = ctx;
md->result_size = int_sha512_len;
md->block_size = int_sha512_block_len;
- md->reset = int_sha512_reset;
- md->update = int_sha512_update;
- md->finish = int_sha512_finish;
- md->free = int_sha512_free;
+ md->reset = int_sha2_reset;
+ md->update = int_sha2_update;
+ md->finish = int_sha2_finish;
+ md->free = int_sha2_free;
md->reset(md);
}
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index c52f20d4ba..149691c26c 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3180,6 +3180,7 @@ pg_mb_radix_tree
pg_on_exit_callback
pg_re_flags
pg_saslprep_rc
+pg_sha2_ctx
pg_sha224_ctx
pg_sha256_ctx
pg_sha384_ctx
--
2.28.0