PostgreSQL Source Code  git master
cryptohashfuncs.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * cryptohashfuncs.c
4  * Cryptographic hash functions
5  *
6  * Portions Copyright (c) 2018-2021, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/utils/adt/cryptohashfuncs.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "common/cryptohash.h"
17 #include "common/md5.h"
18 #include "common/sha2.h"
19 #include "utils/builtins.h"
20 
21 
22 /*
23  * MD5
24  */
25 
26 /* MD5 produces a 16 byte (128 bit) hash; double it for hex */
27 #define MD5_HASH_LEN 32
28 
29 /*
30  * Create an MD5 hash of a text value and return it as hex string.
31  */
32 Datum
34 {
35  text *in_text = PG_GETARG_TEXT_PP(0);
36  size_t len;
37  char hexsum[MD5_HASH_LEN + 1];
38 
39  /* Calculate the length of the buffer using varlena metadata */
40  len = VARSIZE_ANY_EXHDR(in_text);
41 
42  /* get the hash result */
43  if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum) == false)
44  ereport(ERROR,
45  (errcode(ERRCODE_OUT_OF_MEMORY),
46  errmsg("out of memory")));
47 
48  /* convert to text and return it */
50 }
51 
52 /*
53  * Create an MD5 hash of a bytea value and return it as a hex string.
54  */
55 Datum
57 {
58  bytea *in = PG_GETARG_BYTEA_PP(0);
59  size_t len;
60  char hexsum[MD5_HASH_LEN + 1];
61 
62  len = VARSIZE_ANY_EXHDR(in);
63  if (pg_md5_hash(VARDATA_ANY(in), len, hexsum) == false)
64  ereport(ERROR,
65  (errcode(ERRCODE_OUT_OF_MEMORY),
66  errmsg("out of memory")));
67 
69 }
70 
71 /*
72  * Internal routine to compute a cryptohash with the given bytea input.
73  */
74 static inline bytea *
76 {
77  const uint8 *data;
78  const char *typestr = NULL;
79  int digest_len = 0;
80  size_t len;
81  pg_cryptohash_ctx *ctx;
82  bytea *result;
83 
84  switch (type)
85  {
86  case PG_SHA224:
87  typestr = "SHA224";
88  digest_len = PG_SHA224_DIGEST_LENGTH;
89  break;
90  case PG_SHA256:
91  typestr = "SHA256";
92  digest_len = PG_SHA256_DIGEST_LENGTH;
93  break;
94  case PG_SHA384:
95  typestr = "SHA384";
96  digest_len = PG_SHA384_DIGEST_LENGTH;
97  break;
98  case PG_SHA512:
99  typestr = "SHA512";
100  digest_len = PG_SHA512_DIGEST_LENGTH;
101  break;
102  case PG_MD5:
103  case PG_SHA1:
104  elog(ERROR, "unsupported cryptohash type %d", type);
105  break;
106  }
107 
108  result = palloc0(digest_len + VARHDRSZ);
109  len = VARSIZE_ANY_EXHDR(input);
110  data = (unsigned char *) VARDATA_ANY(input);
111 
112  ctx = pg_cryptohash_create(type);
113  if (pg_cryptohash_init(ctx) < 0)
114  elog(ERROR, "could not initialize %s context", typestr);
115  if (pg_cryptohash_update(ctx, data, len) < 0)
116  elog(ERROR, "could not update %s context", typestr);
117  if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result),
118  digest_len) < 0)
119  elog(ERROR, "could not finalize %s context", typestr);
120  pg_cryptohash_free(ctx);
121 
122  SET_VARSIZE(result, digest_len + VARHDRSZ);
123 
124  return result;
125 }
126 
127 /*
128  * SHA-2 variants
129  */
130 
131 Datum
133 {
135 
136  PG_RETURN_BYTEA_P(result);
137 }
138 
139 Datum
141 {
143 
144  PG_RETURN_BYTEA_P(result);
145 }
146 
147 Datum
149 {
151 
152  PG_RETURN_BYTEA_P(result);
153 }
154 
155 Datum
157 {
159 
160  PG_RETURN_BYTEA_P(result);
161 }
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:168
Datum sha384_bytea(PG_FUNCTION_ARGS)
Datum sha256_bytea(PG_FUNCTION_ARGS)
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
#define VARDATA(PTR)
Definition: postgres.h:315
#define VARHDRSZ
Definition: c.h:627
#define PG_SHA256_DIGEST_LENGTH
Definition: sha2.h:22
unsigned char uint8
Definition: c.h:439
static bytea * cryptohash_internal(pg_cryptohash_type type, bytea *input)
int errcode(int sqlerrcode)
Definition: elog.c:698
#define PG_SHA512_DIGEST_LENGTH
Definition: sha2.h:26
Datum sha224_bytea(PG_FUNCTION_ARGS)
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define ERROR
Definition: elog.h:46
bool pg_md5_hash(const void *buff, size_t len, char *hexsum)
Definition: md5_common.c:70
void * palloc0(Size size)
Definition: mcxt.c:1093
uintptr_t Datum
Definition: postgres.h:411
#define MD5_HASH_LEN
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:66
Datum sha512_bytea(PG_FUNCTION_ARGS)
Datum md5_bytea(PG_FUNCTION_ARGS)
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:92
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:130
Datum md5_text(PG_FUNCTION_ARGS)
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
int errmsg(const char *fmt,...)
Definition: elog.c:909
pg_cryptohash_type
Definition: cryptohash.h:19
#define elog(elevel,...)
Definition: elog.h:232
Definition: c.h:621
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:216
#define PG_SHA224_DIGEST_LENGTH
Definition: sha2.h:20
#define PG_SHA384_DIGEST_LENGTH
Definition: sha2.h:24