1 /*-------------------------------------------------------------------------
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
13 * src/common/cryptohash.c
15 *-------------------------------------------------------------------------
21 #include "postgres_fe.h"
24 #include <sys/param.h>
26 #include "common/cryptohash.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.
36 #define ALLOC(size) palloc(size)
37 #define FREE(ptr) pfree(ptr)
39 #define ALLOC(size) malloc(size)
40 #define FREE(ptr) free(ptr)
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
;
68 * pg_cryptohash_create
70 * Allocate a hash context. Returns NULL on failure for an OOM. The
71 * backend issues an error, without returning.
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
84 ctx
= ALLOC(sizeof(pg_cryptohash_ctx
));
88 memset(ctx
, 0, sizeof(pg_cryptohash_ctx
));
90 ctx
->error
= PG_CRYPTOHASH_ERROR_NONE
;
97 * Initialize a hash context. Returns 0 on success, and -1 on failure.
100 pg_cryptohash_init(pg_cryptohash_ctx
*ctx
)
108 pg_md5_init(&ctx
->data
.md5
);
111 pg_sha1_init(&ctx
->data
.sha1
);
114 pg_sha224_init(&ctx
->data
.sha224
);
117 pg_sha256_init(&ctx
->data
.sha256
);
120 pg_sha384_init(&ctx
->data
.sha384
);
123 pg_sha512_init(&ctx
->data
.sha512
);
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
)
144 pg_md5_update(&ctx
->data
.md5
, data
, len
);
147 pg_sha1_update(&ctx
->data
.sha1
, data
, len
);
150 pg_sha224_update(&ctx
->data
.sha224
, data
, len
);
153 pg_sha256_update(&ctx
->data
.sha256
, data
, len
);
156 pg_sha384_update(&ctx
->data
.sha384
, data
, len
);
159 pg_sha512_update(&ctx
->data
.sha512
, data
, len
);
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
)
180 if (len
< MD5_DIGEST_LENGTH
)
182 ctx
->error
= PG_CRYPTOHASH_ERROR_DEST_LEN
;
185 pg_md5_final(&ctx
->data
.md5
, dest
);
188 if (len
< SHA1_DIGEST_LENGTH
)
190 ctx
->error
= PG_CRYPTOHASH_ERROR_DEST_LEN
;
193 pg_sha1_final(&ctx
->data
.sha1
, dest
);
196 if (len
< PG_SHA224_DIGEST_LENGTH
)
198 ctx
->error
= PG_CRYPTOHASH_ERROR_DEST_LEN
;
201 pg_sha224_final(&ctx
->data
.sha224
, dest
);
204 if (len
< PG_SHA256_DIGEST_LENGTH
)
206 ctx
->error
= PG_CRYPTOHASH_ERROR_DEST_LEN
;
209 pg_sha256_final(&ctx
->data
.sha256
, dest
);
212 if (len
< PG_SHA384_DIGEST_LENGTH
)
214 ctx
->error
= PG_CRYPTOHASH_ERROR_DEST_LEN
;
217 pg_sha384_final(&ctx
->data
.sha384
, dest
);
220 if (len
< PG_SHA512_DIGEST_LENGTH
)
222 ctx
->error
= PG_CRYPTOHASH_ERROR_DEST_LEN
;
225 pg_sha512_final(&ctx
->data
.sha512
, dest
);
235 * Free a hash context.
238 pg_cryptohash_free(pg_cryptohash_ctx
*ctx
)
243 explicit_bzero(ctx
, sizeof(pg_cryptohash_ctx
));
248 * pg_cryptohash_error
250 * Returns a static string providing details about an error that
251 * happened during a computation.
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.
261 return _("out of memory");
265 case PG_CRYPTOHASH_ERROR_NONE
:
267 case PG_CRYPTOHASH_ERROR_DEST_LEN
:
268 return _("destination buffer too small");