PostgreSQL Source Code  git master
cryptohash_openssl.c File Reference
#include "postgres.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include "common/cryptohash.h"
#include "common/md5.h"
#include "common/sha1.h"
#include "common/sha2.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
#include "utils/resowner_private.h"
Include dependency graph for cryptohash_openssl.c:

Go to the source code of this file.

Data Structures

struct  pg_cryptohash_ctx
 

Macros

#define ALLOC(size)   MemoryContextAlloc(TopMemoryContext, size)
 
#define FREE(ptr)   pfree(ptr)
 

Typedefs

typedef enum pg_cryptohash_errno pg_cryptohash_errno
 

Enumerations

enum  pg_cryptohash_errno {
  PG_CRYPTOHASH_ERROR_NONE = 0 , PG_CRYPTOHASH_ERROR_DEST_LEN , PG_CRYPTOHASH_ERROR_NONE = 0 , PG_CRYPTOHASH_ERROR_DEST_LEN ,
  PG_CRYPTOHASH_ERROR_OPENSSL
}
 

Functions

static const char * SSLerrmessage (unsigned long ecode)
 
pg_cryptohash_ctxpg_cryptohash_create (pg_cryptohash_type type)
 
int pg_cryptohash_init (pg_cryptohash_ctx *ctx)
 
int pg_cryptohash_update (pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
 
int pg_cryptohash_final (pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
 
void pg_cryptohash_free (pg_cryptohash_ctx *ctx)
 
const char * pg_cryptohash_error (pg_cryptohash_ctx *ctx)
 

Macro Definition Documentation

◆ ALLOC

#define ALLOC (   size)    MemoryContextAlloc(TopMemoryContext, size)

Definition at line 43 of file cryptohash_openssl.c.

◆ FREE

#define FREE (   ptr)    pfree(ptr)

Definition at line 44 of file cryptohash_openssl.c.

Typedef Documentation

◆ pg_cryptohash_errno

Enumeration Type Documentation

◆ pg_cryptohash_errno

Enumerator
PG_CRYPTOHASH_ERROR_NONE 
PG_CRYPTOHASH_ERROR_DEST_LEN 
PG_CRYPTOHASH_ERROR_NONE 
PG_CRYPTOHASH_ERROR_DEST_LEN 
PG_CRYPTOHASH_ERROR_OPENSSL 

Definition at line 51 of file cryptohash_openssl.c.

52 {
pg_cryptohash_errno
@ PG_CRYPTOHASH_ERROR_DEST_LEN
@ PG_CRYPTOHASH_ERROR_NONE
@ PG_CRYPTOHASH_ERROR_OPENSSL

Function Documentation

◆ pg_cryptohash_create()

pg_cryptohash_ctx* pg_cryptohash_create ( pg_cryptohash_type  type)

Definition at line 97 of file cryptohash_openssl.c.

98 {
99  pg_cryptohash_ctx *ctx;
100 
101  /*
102  * Make sure that the resource owner has space to remember this reference.
103  * This can error out with "out of memory", so do this before any other
104  * allocation to avoid leaking.
105  */
106 #ifndef FRONTEND
108 #endif
109 
110  ctx = ALLOC(sizeof(pg_cryptohash_ctx));
111  if (ctx == NULL)
112  return NULL;
113  memset(ctx, 0, sizeof(pg_cryptohash_ctx));
114  ctx->type = type;
116  ctx->errreason = NULL;
117 
118  /*
119  * Initialization takes care of assigning the correct type for OpenSSL.
120  * Also ensure that there aren't any unconsumed errors in the queue from
121  * previous runs.
122  */
123  ERR_clear_error();
124  ctx->evpctx = EVP_MD_CTX_create();
125 
126  if (ctx->evpctx == NULL)
127  {
128  explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
129  FREE(ctx);
130 #ifndef FRONTEND
131  ereport(ERROR,
132  (errcode(ERRCODE_OUT_OF_MEMORY),
133  errmsg("out of memory")));
134 #else
135  return NULL;
136 #endif
137  }
138 
139 #ifndef FRONTEND
142  PointerGetDatum(ctx));
143 #endif
144 
145  return ctx;
146 }
#define FREE(ptr)
#define ALLOC(size)
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
void explicit_bzero(void *buf, size_t len)
#define PointerGetDatum(X)
Definition: postgres.h:600
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void ResourceOwnerRememberCryptoHash(ResourceOwner owner, Datum handle)
Definition: resowner.c:1421
void ResourceOwnerEnlargeCryptoHash(ResourceOwner owner)
Definition: resowner.c:1410
pg_cryptohash_errno error
Definition: cryptohash.c:54
ResourceOwner resowner
pg_cryptohash_type type
Definition: cryptohash.c:53
const char * errreason

References ALLOC, CurrentResourceOwner, ereport, errcode(), errmsg(), pg_cryptohash_ctx::error, ERROR, pg_cryptohash_ctx::errreason, pg_cryptohash_ctx::evpctx, explicit_bzero(), FREE, PG_CRYPTOHASH_ERROR_NONE, PointerGetDatum, ResourceOwnerEnlargeCryptoHash(), ResourceOwnerRememberCryptoHash(), pg_cryptohash_ctx::resowner, generate_unaccent_rules::type, and pg_cryptohash_ctx::type.

◆ pg_cryptohash_error()

const char* pg_cryptohash_error ( pg_cryptohash_ctx ctx)

Definition at line 325 of file cryptohash_openssl.c.

326 {
327  /*
328  * This implementation would never fail because of an out-of-memory error,
329  * except when creating the context.
330  */
331  if (ctx == NULL)
332  return _("out of memory");
333 
334  /*
335  * If a reason is provided, rely on it, else fallback to any error code
336  * set.
337  */
338  if (ctx->errreason)
339  return ctx->errreason;
340 
341  switch (ctx->error)
342  {
344  return _("success");
346  return _("destination buffer too small");
348  return _("OpenSSL failure");
349  }
350 
351  Assert(false); /* cannot be reached */
352  return _("success");
353 }
#define _(x)
Definition: elog.c:89
Assert(fmt[strlen(fmt) - 1] !='\n')

References _, Assert(), pg_cryptohash_ctx::error, pg_cryptohash_ctx::errreason, PG_CRYPTOHASH_ERROR_DEST_LEN, PG_CRYPTOHASH_ERROR_NONE, and PG_CRYPTOHASH_ERROR_OPENSSL.

◆ pg_cryptohash_final()

int pg_cryptohash_final ( pg_cryptohash_ctx ctx,
uint8 dest,
size_t  len 
)

Definition at line 231 of file cryptohash_openssl.c.

232 {
233  int status = 0;
234 
235  if (ctx == NULL)
236  return -1;
237 
238  switch (ctx->type)
239  {
240  case PG_MD5:
241  if (len < MD5_DIGEST_LENGTH)
242  {
244  return -1;
245  }
246  break;
247  case PG_SHA1:
248  if (len < SHA1_DIGEST_LENGTH)
249  {
251  return -1;
252  }
253  break;
254  case PG_SHA224:
256  {
258  return -1;
259  }
260  break;
261  case PG_SHA256:
263  {
265  return -1;
266  }
267  break;
268  case PG_SHA384:
270  {
272  return -1;
273  }
274  break;
275  case PG_SHA512:
277  {
279  return -1;
280  }
281  break;
282  }
283 
284  status = EVP_DigestFinal_ex(ctx->evpctx, dest, 0);
285 
286  /* OpenSSL internals return 1 on success, 0 on failure */
287  if (status <= 0)
288  {
289  ctx->errreason = SSLerrmessage(ERR_get_error());
291  return -1;
292  }
293  return 0;
294 }
@ 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
static const char * SSLerrmessage(unsigned long ecode)
#define MD5_DIGEST_LENGTH
Definition: md5.h:20
const void size_t len
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
#define SHA1_DIGEST_LENGTH
Definition: sha1.h:17
#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

References generate_unaccent_rules::dest, pg_cryptohash_ctx::error, pg_cryptohash_ctx::errreason, pg_cryptohash_ctx::evpctx, len, MD5_DIGEST_LENGTH, PG_CRYPTOHASH_ERROR_DEST_LEN, PG_CRYPTOHASH_ERROR_OPENSSL, PG_MD5, PG_SHA1, PG_SHA224, PG_SHA224_DIGEST_LENGTH, PG_SHA256, PG_SHA256_DIGEST_LENGTH, PG_SHA384, PG_SHA384_DIGEST_LENGTH, PG_SHA512, PG_SHA512_DIGEST_LENGTH, SHA1_DIGEST_LENGTH, SSLerrmessage(), status(), and pg_cryptohash_ctx::type.

◆ pg_cryptohash_free()

void pg_cryptohash_free ( pg_cryptohash_ctx ctx)

Definition at line 302 of file cryptohash_openssl.c.

303 {
304  if (ctx == NULL)
305  return;
306 
307  EVP_MD_CTX_destroy(ctx->evpctx);
308 
309 #ifndef FRONTEND
311  PointerGetDatum(ctx));
312 #endif
313 
314  explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
315  FREE(ctx);
316 }
void ResourceOwnerForgetCryptoHash(ResourceOwner owner, Datum handle)
Definition: resowner.c:1430

References pg_cryptohash_ctx::evpctx, explicit_bzero(), FREE, PointerGetDatum, ResourceOwnerForgetCryptoHash(), and pg_cryptohash_ctx::resowner.

◆ pg_cryptohash_init()

int pg_cryptohash_init ( pg_cryptohash_ctx ctx)

Definition at line 154 of file cryptohash_openssl.c.

155 {
156  int status = 0;
157 
158  if (ctx == NULL)
159  return -1;
160 
161  switch (ctx->type)
162  {
163  case PG_MD5:
164  status = EVP_DigestInit_ex(ctx->evpctx, EVP_md5(), NULL);
165  break;
166  case PG_SHA1:
167  status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha1(), NULL);
168  break;
169  case PG_SHA224:
170  status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha224(), NULL);
171  break;
172  case PG_SHA256:
173  status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha256(), NULL);
174  break;
175  case PG_SHA384:
176  status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha384(), NULL);
177  break;
178  case PG_SHA512:
179  status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha512(), NULL);
180  break;
181  }
182 
183  /* OpenSSL internals return 1 on success, 0 on failure */
184  if (status <= 0)
185  {
186  ctx->errreason = SSLerrmessage(ERR_get_error());
188 
189  /*
190  * The OpenSSL error queue should normally be empty since we've
191  * consumed an error, but cipher initialization can in FIPS-enabled
192  * OpenSSL builds generate two errors so clear the queue here as well.
193  */
194  ERR_clear_error();
195  return -1;
196  }
197  return 0;
198 }

References pg_cryptohash_ctx::error, pg_cryptohash_ctx::errreason, pg_cryptohash_ctx::evpctx, PG_CRYPTOHASH_ERROR_OPENSSL, PG_MD5, PG_SHA1, PG_SHA224, PG_SHA256, PG_SHA384, PG_SHA512, SSLerrmessage(), status(), and pg_cryptohash_ctx::type.

◆ pg_cryptohash_update()

int pg_cryptohash_update ( pg_cryptohash_ctx ctx,
const uint8 data,
size_t  len 
)

Definition at line 206 of file cryptohash_openssl.c.

207 {
208  int status = 0;
209 
210  if (ctx == NULL)
211  return -1;
212 
213  status = EVP_DigestUpdate(ctx->evpctx, data, len);
214 
215  /* OpenSSL internals return 1 on success, 0 on failure */
216  if (status <= 0)
217  {
218  ctx->errreason = SSLerrmessage(ERR_get_error());
220  return -1;
221  }
222  return 0;
223 }
const void * data

References data, pg_cryptohash_ctx::error, pg_cryptohash_ctx::errreason, pg_cryptohash_ctx::evpctx, len, PG_CRYPTOHASH_ERROR_OPENSSL, SSLerrmessage(), and status().

◆ SSLerrmessage()

static const char* SSLerrmessage ( unsigned long  ecode)
static

Definition at line 78 of file cryptohash_openssl.c.

79 {
80  if (ecode == 0)
81  return NULL;
82 
83  /*
84  * This may return NULL, but we would fall back to a default error path if
85  * that were the case.
86  */
87  return ERR_reason_error_string(ecode);
88 }

Referenced by pg_cryptohash_final(), pg_cryptohash_init(), and pg_cryptohash_update().