PostgreSQL Source Code  git master
cryptohash.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * cryptohash.c
4  * Fallback implementations for cryptographic hash functions.
5  *
6  * This is the set of in-core functions used when there are no other
7  * alternative options like OpenSSL.
8  *
9  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
10  * Portions Copyright (c) 1994, Regents of the University of California
11  *
12  * IDENTIFICATION
13  * src/common/cryptohash.c
14  *
15  *-------------------------------------------------------------------------
16  */
17 
18 #ifndef FRONTEND
19 #include "postgres.h"
20 #else
21 #include "postgres_fe.h"
22 #endif
23 
24 #include <sys/param.h>
25 
26 #include "common/cryptohash.h"
27 #include "md5_int.h"
28 #include "sha1_int.h"
29 #include "sha2_int.h"
30 
31 /*
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.
34  */
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
42 
43 /* Set of error states */
44 typedef enum pg_cryptohash_errno
45 {
49 
50 /* Internal pg_cryptohash_ctx structure */
52 {
55 
56  union
57  {
64  } data;
65 };
66 
67 /*
68  * pg_cryptohash_create
69  *
70  * Allocate a hash context. Returns NULL on failure for an OOM. The
71  * backend issues an error, without returning.
72  */
75 {
76  pg_cryptohash_ctx *ctx;
77 
78  /*
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.
83  */
84  ctx = ALLOC(sizeof(pg_cryptohash_ctx));
85  if (ctx == NULL)
86  return NULL;
87 
88  memset(ctx, 0, sizeof(pg_cryptohash_ctx));
89  ctx->type = type;
91  return ctx;
92 }
93 
94 /*
95  * pg_cryptohash_init
96  *
97  * Initialize a hash context. Returns 0 on success, and -1 on failure.
98  */
99 int
101 {
102  if (ctx == NULL)
103  return -1;
104 
105  switch (ctx->type)
106  {
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;
125  }
126 
127  return 0;
128 }
129 
130 /*
131  * pg_cryptohash_update
132  *
133  * Update a hash context. Returns 0 on success, and -1 on failure.
134  */
135 int
137 {
138  if (ctx == NULL)
139  return -1;
140 
141  switch (ctx->type)
142  {
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:
151  break;
152  case PG_SHA256:
154  break;
155  case PG_SHA384:
157  break;
158  case PG_SHA512:
160  break;
161  }
162 
163  return 0;
164 }
165 
166 /*
167  * pg_cryptohash_final
168  *
169  * Finalize a hash context. Returns 0 on success, and -1 on failure.
170  */
171 int
173 {
174  if (ctx == NULL)
175  return -1;
176 
177  switch (ctx->type)
178  {
179  case PG_MD5:
180  if (len < MD5_DIGEST_LENGTH)
181  {
183  return -1;
184  }
185  pg_md5_final(&ctx->data.md5, dest);
186  break;
187  case PG_SHA1:
188  if (len < SHA1_DIGEST_LENGTH)
189  {
191  return -1;
192  }
193  pg_sha1_final(&ctx->data.sha1, dest);
194  break;
195  case PG_SHA224:
197  {
199  return -1;
200  }
202  break;
203  case PG_SHA256:
205  {
207  return -1;
208  }
210  break;
211  case PG_SHA384:
213  {
215  return -1;
216  }
218  break;
219  case PG_SHA512:
221  {
223  return -1;
224  }
226  break;
227  }
228 
229  return 0;
230 }
231 
232 /*
233  * pg_cryptohash_free
234  *
235  * Free a hash context.
236  */
237 void
239 {
240  if (ctx == NULL)
241  return;
242 
243  explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
244  FREE(ctx);
245 }
246 
247 /*
248  * pg_cryptohash_error
249  *
250  * Returns a static string providing details about an error that
251  * happened during a computation.
252  */
253 const char *
255 {
256  /*
257  * This implementation would never fail because of an out-of-memory error,
258  * except when creating the context.
259  */
260  if (ctx == NULL)
261  return _("out of memory");
262 
263  switch (ctx->error)
264  {
266  return _("success");
268  return _("destination buffer too small");
269  }
270 
271  Assert(false);
272  return _("success");
273 }
#define Assert(condition)
Definition: c.h:858
unsigned char uint8
Definition: c.h:504
#define FREE(ptr)
Definition: cryptohash.c:37
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:136
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:100
pg_cryptohash_errno
Definition: cryptohash.c:45
@ PG_CRYPTOHASH_ERROR_DEST_LEN
Definition: cryptohash.c:47
@ PG_CRYPTOHASH_ERROR_NONE
Definition: cryptohash.c:46
#define ALLOC(size)
Definition: cryptohash.c:36
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:238
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:74
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:172
const char * pg_cryptohash_error(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:254
pg_cryptohash_type
Definition: cryptohash.h:20
@ PG_SHA512
Definition: cryptohash.h:26
@ PG_SHA224
Definition: cryptohash.h:23
@ PG_SHA384
Definition: cryptohash.h:25
@ PG_SHA1
Definition: cryptohash.h:22
@ PG_SHA256
Definition: cryptohash.h:24
@ PG_MD5
Definition: cryptohash.h:21
#define _(x)
Definition: elog.c:90
void pg_md5_init(pg_md5_ctx *ctx)
Definition: md5.c:385
void pg_md5_update(pg_md5_ctx *ctx, const uint8 *data, size_t len)
Definition: md5.c:403
void pg_md5_final(pg_md5_ctx *ctx, uint8 *dest)
Definition: md5.c:435
#define MD5_DIGEST_LENGTH
Definition: md5.h:20
const void size_t len
const void * data
void explicit_bzero(void *buf, size_t len)
void pg_sha1_update(pg_sha1_ctx *ctx, const uint8 *data, size_t len)
Definition: sha1.c:332
void pg_sha1_init(pg_sha1_ctx *ctx)
Definition: sha1.c:316
void pg_sha1_final(pg_sha1_ctx *ctx, uint8 *dest)
Definition: sha1.c:365
#define SHA1_DIGEST_LENGTH
Definition: sha1.h:17
void pg_sha512_final(pg_sha512_ctx *context, uint8 *digest)
Definition: sha2.c:905
void pg_sha384_init(pg_sha384_ctx *context)
Definition: sha2.c:934
void pg_sha256_init(pg_sha256_ctx *context)
Definition: sha2.c:279
void pg_sha512_update(pg_sha512_ctx *context, const uint8 *data, size_t len)
Definition: sha2.c:802
void pg_sha224_update(pg_sha224_ctx *context, const uint8 *data, size_t len)
Definition: sha2.c:988
void pg_sha512_init(pg_sha512_ctx *context)
Definition: sha2.c:605
void pg_sha224_init(pg_sha224_ctx *context)
Definition: sha2.c:978
void pg_sha256_final(pg_sha256_ctx *context, uint8 *digest)
Definition: sha2.c:577
void pg_sha224_final(pg_sha224_ctx *context, uint8 *digest)
Definition: sha2.c:994
void pg_sha384_final(pg_sha384_ctx *context, uint8 *digest)
Definition: sha2.c:950
void pg_sha384_update(pg_sha384_ctx *context, const uint8 *data, size_t len)
Definition: sha2.c:944
void pg_sha256_update(pg_sha256_ctx *context, const uint8 *data, size_t len)
Definition: sha2.c:476
#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_cryptohash_errno error
Definition: cryptohash.c:54
union pg_cryptohash_ctx::@40 data
pg_md5_ctx md5
Definition: cryptohash.c:58
pg_cryptohash_type type
Definition: cryptohash.c:53
pg_sha384_ctx sha384
Definition: cryptohash.c:62
pg_sha1_ctx sha1
Definition: cryptohash.c:59
pg_sha256_ctx sha256
Definition: cryptohash.c:61
pg_sha512_ctx sha512
Definition: cryptohash.c:63
pg_sha224_ctx sha224
Definition: cryptohash.c:60
const char * type