PostgreSQL Source Code git master
checksum_helper.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * checksum_helper.c
4 * Compute a checksum of any of various types using common routines
5 *
6 * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/common/checksum_helper.c
10 *
11 *-------------------------------------------------------------------------
12 */
13
14#ifndef FRONTEND
15#include "postgres.h"
16#else
17#include "postgres_fe.h"
18#endif
19
21
22/*
23 * If 'name' is a recognized checksum type, set *type to the corresponding
24 * constant and return true. Otherwise, set *type to CHECKSUM_TYPE_NONE and
25 * return false.
26 */
27bool
29{
31 bool result = true;
32
33 if (pg_strcasecmp(name, "none") == 0)
34 result_type = CHECKSUM_TYPE_NONE;
35 else if (pg_strcasecmp(name, "crc32c") == 0)
36 result_type = CHECKSUM_TYPE_CRC32C;
37 else if (pg_strcasecmp(name, "sha224") == 0)
38 result_type = CHECKSUM_TYPE_SHA224;
39 else if (pg_strcasecmp(name, "sha256") == 0)
40 result_type = CHECKSUM_TYPE_SHA256;
41 else if (pg_strcasecmp(name, "sha384") == 0)
42 result_type = CHECKSUM_TYPE_SHA384;
43 else if (pg_strcasecmp(name, "sha512") == 0)
44 result_type = CHECKSUM_TYPE_SHA512;
45 else
46 result = false;
47
48 *type = result_type;
49 return result;
50}
51
52/*
53 * Get the canonical human-readable name corresponding to a checksum type.
54 */
55char *
57{
58 switch (type)
59 {
61 return "NONE";
63 return "CRC32C";
65 return "SHA224";
67 return "SHA256";
69 return "SHA384";
71 return "SHA512";
72 }
73
74 Assert(false);
75 return "???";
76}
77
78/*
79 * Initialize a checksum context for checksums of the given type.
80 * Returns 0 for a success, -1 for a failure.
81 */
82int
84{
85 context->type = type;
86
87 switch (type)
88 {
90 /* do nothing */
91 break;
94 break;
97 if (context->raw_context.c_sha2 == NULL)
98 return -1;
99 if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
100 {
102 return -1;
103 }
104 break;
107 if (context->raw_context.c_sha2 == NULL)
108 return -1;
109 if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
110 {
112 return -1;
113 }
114 break;
117 if (context->raw_context.c_sha2 == NULL)
118 return -1;
119 if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
120 {
122 return -1;
123 }
124 break;
127 if (context->raw_context.c_sha2 == NULL)
128 return -1;
129 if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
130 {
132 return -1;
133 }
134 break;
135 }
136
137 return 0;
138}
139
140/*
141 * Update a checksum context with new data.
142 * Returns 0 for a success, -1 for a failure.
143 */
144int
146 size_t len)
147{
148 switch (context->type)
149 {
151 /* do nothing */
152 break;
155 break;
160 if (pg_cryptohash_update(context->raw_context.c_sha2, input, len) < 0)
161 return -1;
162 break;
163 }
164
165 return 0;
166}
167
168/*
169 * Finalize a checksum computation and write the result to an output buffer.
170 *
171 * The caller must ensure that the buffer is at least PG_CHECKSUM_MAX_LENGTH
172 * bytes in length. The return value is the number of bytes actually written,
173 * or -1 for a failure.
174 */
175int
177{
178 int retval = 0;
179
181 "CRC-32C digest too big for PG_CHECKSUM_MAX_LENGTH");
183 "SHA224 digest too big for PG_CHECKSUM_MAX_LENGTH");
185 "SHA256 digest too big for PG_CHECKSUM_MAX_LENGTH");
187 "SHA384 digest too big for PG_CHECKSUM_MAX_LENGTH");
189 "SHA512 digest too big for PG_CHECKSUM_MAX_LENGTH");
190
191 switch (context->type)
192 {
194 break;
197 retval = sizeof(pg_crc32c);
198 memcpy(output, &context->raw_context.c_crc32c, retval);
199 break;
203 output, retval) < 0)
204 return -1;
206 break;
210 output, retval) < 0)
211 return -1;
213 break;
217 output, retval) < 0)
218 return -1;
220 break;
224 output, retval) < 0)
225 return -1;
227 break;
228 }
229
231 return retval;
232}
uint8_t uint8
Definition: c.h:500
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:907
bool pg_checksum_parse_type(char *name, pg_checksum_type *type)
int pg_checksum_final(pg_checksum_context *context, uint8 *output)
char * pg_checksum_type_name(pg_checksum_type type)
int pg_checksum_update(pg_checksum_context *context, const uint8 *input, size_t len)
int pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
#define PG_CHECKSUM_MAX_LENGTH
pg_checksum_type
@ CHECKSUM_TYPE_SHA384
@ CHECKSUM_TYPE_SHA256
@ CHECKSUM_TYPE_SHA224
@ CHECKSUM_TYPE_NONE
@ CHECKSUM_TYPE_CRC32C
@ CHECKSUM_TYPE_SHA512
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:136
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:74
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:100
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:238
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:172
@ PG_SHA512
Definition: cryptohash.h:26
@ PG_SHA224
Definition: cryptohash.h:23
@ PG_SHA384
Definition: cryptohash.h:25
@ PG_SHA256
Definition: cryptohash.h:24
Assert(PointerIsAligned(start, uint64))
FILE * input
FILE * output
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:98
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:103
const void size_t len
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define PG_SHA256_DIGEST_LENGTH
Definition: sha2.h:23
#define PG_SHA384_DIGEST_LENGTH
Definition: sha2.h:26
#define PG_SHA512_DIGEST_LENGTH
Definition: sha2.h:29
#define PG_SHA224_DIGEST_LENGTH
Definition: sha2.h:20
pg_checksum_type type
pg_checksum_raw_context raw_context
pg_cryptohash_ctx * c_sha2
const char * type
const char * name