jsonpath scanner: reentrant scanner
[pgsql.git] / src / common / checksum_helper.c
blobcc111401aebeb6993d1c5cf7f0db0c5a1926edef
1 /*-------------------------------------------------------------------------
3 * checksum_helper.c
4 * Compute a checksum of any of various types using common routines
6 * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group
8 * IDENTIFICATION
9 * src/common/checksum_helper.c
11 *-------------------------------------------------------------------------
14 #ifndef FRONTEND
15 #include "postgres.h"
16 #else
17 #include "postgres_fe.h"
18 #endif
20 #include "common/checksum_helper.h"
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.
27 bool
28 pg_checksum_parse_type(char *name, pg_checksum_type *type)
30 pg_checksum_type result_type = CHECKSUM_TYPE_NONE;
31 bool result = true;
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;
48 *type = result_type;
49 return result;
53 * Get the canonical human-readable name corresponding to a checksum type.
55 char *
56 pg_checksum_type_name(pg_checksum_type type)
58 switch (type)
60 case CHECKSUM_TYPE_NONE:
61 return "NONE";
62 case CHECKSUM_TYPE_CRC32C:
63 return "CRC32C";
64 case CHECKSUM_TYPE_SHA224:
65 return "SHA224";
66 case CHECKSUM_TYPE_SHA256:
67 return "SHA256";
68 case CHECKSUM_TYPE_SHA384:
69 return "SHA384";
70 case CHECKSUM_TYPE_SHA512:
71 return "SHA512";
74 Assert(false);
75 return "???";
79 * Initialize a checksum context for checksums of the given type.
80 * Returns 0 for a success, -1 for a failure.
82 int
83 pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
85 context->type = type;
87 switch (type)
89 case CHECKSUM_TYPE_NONE:
90 /* do nothing */
91 break;
92 case CHECKSUM_TYPE_CRC32C:
93 INIT_CRC32C(context->raw_context.c_crc32c);
94 break;
95 case CHECKSUM_TYPE_SHA224:
96 context->raw_context.c_sha2 = pg_cryptohash_create(PG_SHA224);
97 if (context->raw_context.c_sha2 == NULL)
98 return -1;
99 if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
101 pg_cryptohash_free(context->raw_context.c_sha2);
102 return -1;
104 break;
105 case CHECKSUM_TYPE_SHA256:
106 context->raw_context.c_sha2 = pg_cryptohash_create(PG_SHA256);
107 if (context->raw_context.c_sha2 == NULL)
108 return -1;
109 if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
111 pg_cryptohash_free(context->raw_context.c_sha2);
112 return -1;
114 break;
115 case CHECKSUM_TYPE_SHA384:
116 context->raw_context.c_sha2 = pg_cryptohash_create(PG_SHA384);
117 if (context->raw_context.c_sha2 == NULL)
118 return -1;
119 if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
121 pg_cryptohash_free(context->raw_context.c_sha2);
122 return -1;
124 break;
125 case CHECKSUM_TYPE_SHA512:
126 context->raw_context.c_sha2 = pg_cryptohash_create(PG_SHA512);
127 if (context->raw_context.c_sha2 == NULL)
128 return -1;
129 if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
131 pg_cryptohash_free(context->raw_context.c_sha2);
132 return -1;
134 break;
137 return 0;
141 * Update a checksum context with new data.
142 * Returns 0 for a success, -1 for a failure.
145 pg_checksum_update(pg_checksum_context *context, const uint8 *input,
146 size_t len)
148 switch (context->type)
150 case CHECKSUM_TYPE_NONE:
151 /* do nothing */
152 break;
153 case CHECKSUM_TYPE_CRC32C:
154 COMP_CRC32C(context->raw_context.c_crc32c, input, len);
155 break;
156 case CHECKSUM_TYPE_SHA224:
157 case CHECKSUM_TYPE_SHA256:
158 case CHECKSUM_TYPE_SHA384:
159 case CHECKSUM_TYPE_SHA512:
160 if (pg_cryptohash_update(context->raw_context.c_sha2, input, len) < 0)
161 return -1;
162 break;
165 return 0;
169 * Finalize a checksum computation and write the result to an output buffer.
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.
176 pg_checksum_final(pg_checksum_context *context, uint8 *output)
178 int retval = 0;
180 StaticAssertDecl(sizeof(pg_crc32c) <= PG_CHECKSUM_MAX_LENGTH,
181 "CRC-32C digest too big for PG_CHECKSUM_MAX_LENGTH");
182 StaticAssertDecl(PG_SHA224_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
183 "SHA224 digest too big for PG_CHECKSUM_MAX_LENGTH");
184 StaticAssertDecl(PG_SHA256_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
185 "SHA256 digest too big for PG_CHECKSUM_MAX_LENGTH");
186 StaticAssertDecl(PG_SHA384_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
187 "SHA384 digest too big for PG_CHECKSUM_MAX_LENGTH");
188 StaticAssertDecl(PG_SHA512_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
189 "SHA512 digest too big for PG_CHECKSUM_MAX_LENGTH");
191 switch (context->type)
193 case CHECKSUM_TYPE_NONE:
194 break;
195 case CHECKSUM_TYPE_CRC32C:
196 FIN_CRC32C(context->raw_context.c_crc32c);
197 retval = sizeof(pg_crc32c);
198 memcpy(output, &context->raw_context.c_crc32c, retval);
199 break;
200 case CHECKSUM_TYPE_SHA224:
201 retval = PG_SHA224_DIGEST_LENGTH;
202 if (pg_cryptohash_final(context->raw_context.c_sha2,
203 output, retval) < 0)
204 return -1;
205 pg_cryptohash_free(context->raw_context.c_sha2);
206 break;
207 case CHECKSUM_TYPE_SHA256:
208 retval = PG_SHA256_DIGEST_LENGTH;
209 if (pg_cryptohash_final(context->raw_context.c_sha2,
210 output, retval) < 0)
211 return -1;
212 pg_cryptohash_free(context->raw_context.c_sha2);
213 break;
214 case CHECKSUM_TYPE_SHA384:
215 retval = PG_SHA384_DIGEST_LENGTH;
216 if (pg_cryptohash_final(context->raw_context.c_sha2,
217 output, retval) < 0)
218 return -1;
219 pg_cryptohash_free(context->raw_context.c_sha2);
220 break;
221 case CHECKSUM_TYPE_SHA512:
222 retval = PG_SHA512_DIGEST_LENGTH;
223 if (pg_cryptohash_final(context->raw_context.c_sha2,
224 output, retval) < 0)
225 return -1;
226 pg_cryptohash_free(context->raw_context.c_sha2);
227 break;
230 Assert(retval <= PG_CHECKSUM_MAX_LENGTH);
231 return retval;