--- /dev/null
   +/*-------------------------------------------------------------------------
 + *
 + * checksum_helper.c
 + *   Compute a checksum of any of various types using common routines
 + *
 + * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
 + *
 + * IDENTIFICATION
 + *       src/common/checksum_helper.c
 + *
 + *-------------------------------------------------------------------------
 + */
 +
 +#ifndef FRONTEND
 +#include "postgres.h"
 +#else
 +#include "postgres_fe.h"
 +#endif
 +
 +#include "common/checksum_helper.h"
 +
 +/*
 + * If 'name' is a recognized checksum type, set *type to the corresponding
 + * constant and return true. Otherwise, set *type to CHECKSUM_TYPE_NONE and
 + * return false.
 + */
 +bool
 +pg_checksum_parse_type(char *name, pg_checksum_type *type)
 +{
 +   pg_checksum_type result_type = CHECKSUM_TYPE_NONE;
 +   bool        result = true;
 +
 +   if (pg_strcasecmp(name, "none") == 0)
 +       result_type = CHECKSUM_TYPE_NONE;
 +   else if (pg_strcasecmp(name, "crc32c") == 0)
 +       result_type = CHECKSUM_TYPE_CRC32C;
 +   else if (pg_strcasecmp(name, "sha224") == 0)
 +       result_type = CHECKSUM_TYPE_SHA224;
 +   else if (pg_strcasecmp(name, "sha256") == 0)
 +       result_type = CHECKSUM_TYPE_SHA256;
 +   else if (pg_strcasecmp(name, "sha384") == 0)
 +       result_type = CHECKSUM_TYPE_SHA384;
 +   else if (pg_strcasecmp(name, "sha512") == 0)
 +       result_type = CHECKSUM_TYPE_SHA512;
 +   else
 +       result = false;
 +
 +   *type = result_type;
 +   return result;
 +}
 +
 +/*
 + * Get the canonical human-readable name corresponding to a checksum type.
 + */
 +char *
 +pg_checksum_type_name(pg_checksum_type type)
 +{
 +   switch (type)
 +   {
 +       case CHECKSUM_TYPE_NONE:
 +           return "NONE";
 +       case CHECKSUM_TYPE_CRC32C:
 +           return "CRC32C";
 +       case CHECKSUM_TYPE_SHA224:
 +           return "SHA224";
 +       case CHECKSUM_TYPE_SHA256:
 +           return "SHA256";
 +       case CHECKSUM_TYPE_SHA384:
 +           return "SHA384";
 +       case CHECKSUM_TYPE_SHA512:
 +           return "SHA512";
 +   }
 +
 +   Assert(false);
 +   return "???";
 +}
 +
 +/*
 + * Initialize a checksum context for checksums of the given type.
 + */
 +void
 +pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
 +{
 +   context->type = type;
 +
 +   switch (type)
 +   {
 +       case CHECKSUM_TYPE_NONE:
 +           /* do nothing */
 +           break;
 +       case CHECKSUM_TYPE_CRC32C:
 +           INIT_CRC32C(context->raw_context.c_crc32c);
 +           break;
 +       case CHECKSUM_TYPE_SHA224:
 +           pg_sha224_init(&context->raw_context.c_sha224);
 +           break;
 +       case CHECKSUM_TYPE_SHA256:
 +           pg_sha256_init(&context->raw_context.c_sha256);
 +           break;
 +       case CHECKSUM_TYPE_SHA384:
 +           pg_sha384_init(&context->raw_context.c_sha384);
 +           break;
 +       case CHECKSUM_TYPE_SHA512:
 +           pg_sha512_init(&context->raw_context.c_sha512);
 +           break;
 +   }
 +}
 +
 +/*
 + * Update a checksum context with new data.
 + */
 +void
 +pg_checksum_update(pg_checksum_context *context, const uint8 *input,
 +                  size_t len)
 +{
 +   switch (context->type)
 +   {
 +       case CHECKSUM_TYPE_NONE:
 +           /* do nothing */
 +           break;
 +       case CHECKSUM_TYPE_CRC32C:
 +           COMP_CRC32C(context->raw_context.c_crc32c, input, len);
 +           break;
 +       case CHECKSUM_TYPE_SHA224:
 +           pg_sha224_update(&context->raw_context.c_sha224, input, len);
 +           break;
 +       case CHECKSUM_TYPE_SHA256:
 +           pg_sha256_update(&context->raw_context.c_sha256, input, len);
 +           break;
 +       case CHECKSUM_TYPE_SHA384:
 +           pg_sha384_update(&context->raw_context.c_sha384, input, len);
 +           break;
 +       case CHECKSUM_TYPE_SHA512:
 +           pg_sha512_update(&context->raw_context.c_sha512, input, len);
 +           break;
 +   }
 +}
 +
 +/*
 + * 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.
 + */
 +int
 +pg_checksum_final(pg_checksum_context *context, uint8 *output)
 +{
 +   int         retval = 0;
 +
 +   StaticAssertStmt(sizeof(pg_crc32c) <= PG_CHECKSUM_MAX_LENGTH,
 +                    "CRC-32C digest too big for PG_CHECKSUM_MAX_LENGTH");
 +   StaticAssertStmt(PG_SHA224_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
 +                    "SHA224 digest too for PG_CHECKSUM_MAX_LENGTH");
 +   StaticAssertStmt(PG_SHA256_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
 +                    "SHA256 digest too for PG_CHECKSUM_MAX_LENGTH");
 +   StaticAssertStmt(PG_SHA384_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
 +                    "SHA384 digest too for PG_CHECKSUM_MAX_LENGTH");
 +   StaticAssertStmt(PG_SHA512_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
 +                    "SHA512 digest too for PG_CHECKSUM_MAX_LENGTH");
 +
 +   switch (context->type)
 +   {
 +       case CHECKSUM_TYPE_NONE:
 +           break;
 +       case CHECKSUM_TYPE_CRC32C:
 +           FIN_CRC32C(context->raw_context.c_crc32c);
 +           retval = sizeof(pg_crc32c);
 +           memcpy(output, &context->raw_context.c_crc32c, retval);
 +           break;
 +       case CHECKSUM_TYPE_SHA224:
 +           pg_sha224_final(&context->raw_context.c_sha224, output);
 +           retval = PG_SHA224_DIGEST_LENGTH;
 +           break;
 +       case CHECKSUM_TYPE_SHA256:
 +           pg_sha256_final(&context->raw_context.c_sha256, output);
 +           retval = PG_SHA256_DIGEST_LENGTH;
 +           break;
 +       case CHECKSUM_TYPE_SHA384:
 +           pg_sha384_final(&context->raw_context.c_sha384, output);
 +           retval = PG_SHA384_DIGEST_LENGTH;
 +           break;
 +       case CHECKSUM_TYPE_SHA512:
 +           pg_sha512_final(&context->raw_context.c_sha512, output);
 +           retval = PG_SHA512_DIGEST_LENGTH;
 +           break;
 +   }
 +
 +   Assert(retval <= PG_CHECKSUM_MAX_LENGTH);
 +   return retval;
 +}
      --- /dev/null
   +/*-------------------------------------------------------------------------
 + *
 + * checksum_helper.h
 + *   Compute a checksum of any of various types using common routines
 + *
 + * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
 + *
 + * IDENTIFICATION
 + *       src/include/common/checksum_helper.h
 + *
 + *-------------------------------------------------------------------------
 + */
 +
 +#ifndef CHECKSUM_HELPER_H
 +#define CHECKSUM_HELPER_H
 +
 +#include "common/sha2.h"
 +#include "port/pg_crc32c.h"
 +
 +/*
 + * Supported checksum types. It's not necessarily the case that code using
 + * these functions needs a cryptographically strong checksum; it may only
 + * need to detect accidental modification. That's why we include CRC-32C: it's
 + * much faster than any of the other algorithms. On the other hand, we omit
 + * MD5 here because any new that does need a cryptographically strong checksum
 + * should use something better.
 + */
 +typedef enum pg_checksum_type
 +{
 +   CHECKSUM_TYPE_NONE,
 +   CHECKSUM_TYPE_CRC32C,
 +   CHECKSUM_TYPE_SHA224,
 +   CHECKSUM_TYPE_SHA256,
 +   CHECKSUM_TYPE_SHA384,
 +   CHECKSUM_TYPE_SHA512
 +} pg_checksum_type;
 +
 +/*
 + * This is just a union of all applicable context types.
 + */
 +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_checksum_raw_context;
 +
 +/*
 + * This structure provides a convenient way to pass the checksum type and the
 + * checksum context around together.
 + */
 +typedef struct pg_checksum_context
 +{
 +   pg_checksum_type type;
 +   pg_checksum_raw_context raw_context;
 +} pg_checksum_context;
 +
 +/*
 + * This is the longest possible output for any checksum algorithm supported
 + * by this file.
 + */
 +#define PG_CHECKSUM_MAX_LENGTH     PG_SHA512_DIGEST_LENGTH
 +
 +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,
 +                              size_t len);
 +extern int pg_checksum_final(pg_checksum_context *, uint8 *output);
 +
 +#endif