doc PG 17 relnotes: add FETCH_COUNT item
[pgsql.git] / src / common / cryptohash.c
blobc96f241dc995893103d96d16dd0407077350cf79
1 /*-------------------------------------------------------------------------
3 * cryptohash.c
4 * Fallback implementations for cryptographic hash functions.
6 * This is the set of in-core functions used when there are no other
7 * alternative options like OpenSSL.
9 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
12 * IDENTIFICATION
13 * src/common/cryptohash.c
15 *-------------------------------------------------------------------------
18 #ifndef FRONTEND
19 #include "postgres.h"
20 #else
21 #include "postgres_fe.h"
22 #endif
24 #include <sys/param.h>
26 #include "common/cryptohash.h"
27 #include "md5_int.h"
28 #include "sha1_int.h"
29 #include "sha2_int.h"
32 * In backend, use palloc/pfree to ease the error handling. In frontend,
33 * use malloc to be able to return a failure status back to the caller.
35 #ifndef FRONTEND
36 #define ALLOC(size) palloc(size)
37 #define FREE(ptr) pfree(ptr)
38 #else
39 #define ALLOC(size) malloc(size)
40 #define FREE(ptr) free(ptr)
41 #endif
43 /* Set of error states */
44 typedef enum pg_cryptohash_errno
46 PG_CRYPTOHASH_ERROR_NONE = 0,
47 PG_CRYPTOHASH_ERROR_DEST_LEN,
48 } pg_cryptohash_errno;
50 /* Internal pg_cryptohash_ctx structure */
51 struct pg_cryptohash_ctx
53 pg_cryptohash_type type;
54 pg_cryptohash_errno error;
56 union
58 pg_md5_ctx md5;
59 pg_sha1_ctx sha1;
60 pg_sha224_ctx sha224;
61 pg_sha256_ctx sha256;
62 pg_sha384_ctx sha384;
63 pg_sha512_ctx sha512;
64 } data;
68 * pg_cryptohash_create
70 * Allocate a hash context. Returns NULL on failure for an OOM. The
71 * backend issues an error, without returning.
73 pg_cryptohash_ctx *
74 pg_cryptohash_create(pg_cryptohash_type type)
76 pg_cryptohash_ctx *ctx;
79 * Note that this always allocates enough space for the largest hash. A
80 * smaller allocation would be enough for md5, sha224 and sha256, but the
81 * small extra amount of memory does not make it worth complicating this
82 * code.
84 ctx = ALLOC(sizeof(pg_cryptohash_ctx));
85 if (ctx == NULL)
86 return NULL;
88 memset(ctx, 0, sizeof(pg_cryptohash_ctx));
89 ctx->type = type;
90 ctx->error = PG_CRYPTOHASH_ERROR_NONE;
91 return ctx;
95 * pg_cryptohash_init
97 * Initialize a hash context. Returns 0 on success, and -1 on failure.
99 int
100 pg_cryptohash_init(pg_cryptohash_ctx *ctx)
102 if (ctx == NULL)
103 return -1;
105 switch (ctx->type)
107 case PG_MD5:
108 pg_md5_init(&ctx->data.md5);
109 break;
110 case PG_SHA1:
111 pg_sha1_init(&ctx->data.sha1);
112 break;
113 case PG_SHA224:
114 pg_sha224_init(&ctx->data.sha224);
115 break;
116 case PG_SHA256:
117 pg_sha256_init(&ctx->data.sha256);
118 break;
119 case PG_SHA384:
120 pg_sha384_init(&ctx->data.sha384);
121 break;
122 case PG_SHA512:
123 pg_sha512_init(&ctx->data.sha512);
124 break;
127 return 0;
131 * pg_cryptohash_update
133 * Update a hash context. Returns 0 on success, and -1 on failure.
136 pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
138 if (ctx == NULL)
139 return -1;
141 switch (ctx->type)
143 case PG_MD5:
144 pg_md5_update(&ctx->data.md5, data, len);
145 break;
146 case PG_SHA1:
147 pg_sha1_update(&ctx->data.sha1, data, len);
148 break;
149 case PG_SHA224:
150 pg_sha224_update(&ctx->data.sha224, data, len);
151 break;
152 case PG_SHA256:
153 pg_sha256_update(&ctx->data.sha256, data, len);
154 break;
155 case PG_SHA384:
156 pg_sha384_update(&ctx->data.sha384, data, len);
157 break;
158 case PG_SHA512:
159 pg_sha512_update(&ctx->data.sha512, data, len);
160 break;
163 return 0;
167 * pg_cryptohash_final
169 * Finalize a hash context. Returns 0 on success, and -1 on failure.
172 pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
174 if (ctx == NULL)
175 return -1;
177 switch (ctx->type)
179 case PG_MD5:
180 if (len < MD5_DIGEST_LENGTH)
182 ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
183 return -1;
185 pg_md5_final(&ctx->data.md5, dest);
186 break;
187 case PG_SHA1:
188 if (len < SHA1_DIGEST_LENGTH)
190 ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
191 return -1;
193 pg_sha1_final(&ctx->data.sha1, dest);
194 break;
195 case PG_SHA224:
196 if (len < PG_SHA224_DIGEST_LENGTH)
198 ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
199 return -1;
201 pg_sha224_final(&ctx->data.sha224, dest);
202 break;
203 case PG_SHA256:
204 if (len < PG_SHA256_DIGEST_LENGTH)
206 ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
207 return -1;
209 pg_sha256_final(&ctx->data.sha256, dest);
210 break;
211 case PG_SHA384:
212 if (len < PG_SHA384_DIGEST_LENGTH)
214 ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
215 return -1;
217 pg_sha384_final(&ctx->data.sha384, dest);
218 break;
219 case PG_SHA512:
220 if (len < PG_SHA512_DIGEST_LENGTH)
222 ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
223 return -1;
225 pg_sha512_final(&ctx->data.sha512, dest);
226 break;
229 return 0;
233 * pg_cryptohash_free
235 * Free a hash context.
237 void
238 pg_cryptohash_free(pg_cryptohash_ctx *ctx)
240 if (ctx == NULL)
241 return;
243 explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
244 FREE(ctx);
248 * pg_cryptohash_error
250 * Returns a static string providing details about an error that
251 * happened during a computation.
253 const char *
254 pg_cryptohash_error(pg_cryptohash_ctx *ctx)
257 * This implementation would never fail because of an out-of-memory error,
258 * except when creating the context.
260 if (ctx == NULL)
261 return _("out of memory");
263 switch (ctx->error)
265 case PG_CRYPTOHASH_ERROR_NONE:
266 return _("success");
267 case PG_CRYPTOHASH_ERROR_DEST_LEN:
268 return _("destination buffer too small");
271 Assert(false);
272 return _("success");