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-2022, 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. Note that this implementation is designed
98  * to never fail, so this always returns 0.
99  */
100 int
102 {
103  if (ctx == NULL)
104  return -1;
105 
106  switch (ctx->type)
107  {
108  case PG_MD5:
109  pg_md5_init(&ctx->data.md5);
110  break;
111  case PG_SHA1:
112  pg_sha1_init(&ctx->data.sha1);
113  break;
114  case PG_SHA224:
115  pg_sha224_init(&ctx->data.sha224);
116  break;
117  case PG_SHA256:
118  pg_sha256_init(&ctx->data.sha256);
119  break;
120  case PG_SHA384:
121  pg_sha384_init(&ctx->data.sha384);
122  break;
123  case PG_SHA512:
124  pg_sha512_init(&ctx->data.sha512);
125  break;
126  }
127 
128  return 0;
129 }
130 
131 /*
132  * pg_cryptohash_update
133  *
134  * Update a hash context. Note that this implementation is designed
135  * to never fail, so this always returns 0 except if the caller has
136  * given a NULL context.
137  */
138 int
140 {
141  if (ctx == NULL)
142  return -1;
143 
144  switch (ctx->type)
145  {
146  case PG_MD5:
147  pg_md5_update(&ctx->data.md5, data, len);
148  break;
149  case PG_SHA1:
150  pg_sha1_update(&ctx->data.sha1, data, len);
151  break;
152  case PG_SHA224:
154  break;
155  case PG_SHA256:
157  break;
158  case PG_SHA384:
160  break;
161  case PG_SHA512:
163  break;
164  }
165 
166  return 0;
167 }
168 
169 /*
170  * pg_cryptohash_final
171  *
172  * Finalize a hash context. Note that this implementation is designed to
173  * never fail, so this always returns 0 except if the destination buffer
174  * is not large enough.
175  */
176 int
178 {
179  if (ctx == NULL)
180  return -1;
181 
182  switch (ctx->type)
183  {
184  case PG_MD5:
185  if (len < MD5_DIGEST_LENGTH)
186  {
188  return -1;
189  }
190  pg_md5_final(&ctx->data.md5, dest);
191  break;
192  case PG_SHA1:
193  if (len < SHA1_DIGEST_LENGTH)
194  {
196  return -1;
197  }
198  pg_sha1_final(&ctx->data.sha1, dest);
199  break;
200  case PG_SHA224:
202  {
204  return -1;
205  }
207  break;
208  case PG_SHA256:
210  {
212  return -1;
213  }
215  break;
216  case PG_SHA384:
218  {
220  return -1;
221  }
223  break;
224  case PG_SHA512:
226  {
228  return -1;
229  }
231  break;
232  }
233 
234  return 0;
235 }
236 
237 /*
238  * pg_cryptohash_free
239  *
240  * Free a hash context.
241  */
242 void
244 {
245  if (ctx == NULL)
246  return;
247 
248  explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
249  FREE(ctx);
250 }
251 
252 /*
253  * pg_cryptohash_error
254  *
255  * Returns a static string providing details about an error that
256  * happened during a computation.
257  */
258 const char *
260 {
261  /*
262  * This implementation would never fail because of an out-of-memory error,
263  * except when creating the context.
264  */
265  if (ctx == NULL)
266  return _("out of memory");
267 
268  switch (ctx->error)
269  {
271  return _("success");
273  return _("destination buffer too small");
274  }
275 
276  Assert(false);
277  return _("success");
278 }
unsigned char uint8
Definition: c.h:439
#define FREE(ptr)
Definition: cryptohash.c:37
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:139
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:101
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:243
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:177
const char * pg_cryptohash_error(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:259
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:89
Assert(fmt[strlen(fmt) - 1] !='\n')
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
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
union pg_cryptohash_ctx::@34 data
pg_sha224_ctx sha224
Definition: cryptohash.c:60