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-2024, 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 #include "varatt.h"
21 
22 
23 /*
24  * MD5
25  */
26 
27 /* MD5 produces a 16 byte (128 bit) hash; double it for hex */
28 #define MD5_HASH_LEN 32
29 
30 /*
31  * Create an MD5 hash of a text value and return it as hex string.
32  */
33 Datum
35 {
36  text *in_text = PG_GETARG_TEXT_PP(0);
37  size_t len;
38  char hexsum[MD5_HASH_LEN + 1];
39  const char *errstr = NULL;
40 
41  /* Calculate the length of the buffer using varlena metadata */
42  len = VARSIZE_ANY_EXHDR(in_text);
43 
44  /* get the hash result */
45  if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum, &errstr) == false)
46  ereport(ERROR,
47  (errcode(ERRCODE_INTERNAL_ERROR),
48  errmsg("could not compute %s hash: %s", "MD5",
49  errstr)));
50 
51  /* convert to text and return it */
53 }
54 
55 /*
56  * Create an MD5 hash of a bytea value and return it as a hex string.
57  */
58 Datum
60 {
61  bytea *in = PG_GETARG_BYTEA_PP(0);
62  size_t len;
63  char hexsum[MD5_HASH_LEN + 1];
64  const char *errstr = NULL;
65 
66  len = VARSIZE_ANY_EXHDR(in);
67  if (pg_md5_hash(VARDATA_ANY(in), len, hexsum, &errstr) == false)
68  ereport(ERROR,
69  (errcode(ERRCODE_INTERNAL_ERROR),
70  errmsg("could not compute %s hash: %s", "MD5",
71  errstr)));
72 
74 }
75 
76 /*
77  * Internal routine to compute a cryptohash with the given bytea input.
78  */
79 static inline bytea *
81 {
82  const uint8 *data;
83  const char *typestr = NULL;
84  int digest_len = 0;
85  size_t len;
86  pg_cryptohash_ctx *ctx;
87  bytea *result;
88 
89  switch (type)
90  {
91  case PG_SHA224:
92  typestr = "SHA224";
93  digest_len = PG_SHA224_DIGEST_LENGTH;
94  break;
95  case PG_SHA256:
96  typestr = "SHA256";
97  digest_len = PG_SHA256_DIGEST_LENGTH;
98  break;
99  case PG_SHA384:
100  typestr = "SHA384";
101  digest_len = PG_SHA384_DIGEST_LENGTH;
102  break;
103  case PG_SHA512:
104  typestr = "SHA512";
105  digest_len = PG_SHA512_DIGEST_LENGTH;
106  break;
107  case PG_MD5:
108  case PG_SHA1:
109  elog(ERROR, "unsupported cryptohash type %d", type);
110  break;
111  }
112 
113  result = palloc0(digest_len + VARHDRSZ);
115  data = (unsigned char *) VARDATA_ANY(input);
116 
117  ctx = pg_cryptohash_create(type);
118  if (pg_cryptohash_init(ctx) < 0)
119  elog(ERROR, "could not initialize %s context: %s", typestr,
120  pg_cryptohash_error(ctx));
121  if (pg_cryptohash_update(ctx, data, len) < 0)
122  elog(ERROR, "could not update %s context: %s", typestr,
123  pg_cryptohash_error(ctx));
124  if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result),
125  digest_len) < 0)
126  elog(ERROR, "could not finalize %s context: %s", typestr,
127  pg_cryptohash_error(ctx));
128  pg_cryptohash_free(ctx);
129 
130  SET_VARSIZE(result, digest_len + VARHDRSZ);
131 
132  return result;
133 }
134 
135 /*
136  * SHA-2 variants
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 }
162 
163 Datum
165 {
167 
168  PG_RETURN_BYTEA_P(result);
169 }
#define VARHDRSZ
Definition: c.h:692
unsigned char uint8
Definition: c.h:504
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
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
Datum md5_bytea(PG_FUNCTION_ARGS)
Datum sha384_bytea(PG_FUNCTION_ARGS)
Datum sha256_bytea(PG_FUNCTION_ARGS)
#define MD5_HASH_LEN
Datum sha512_bytea(PG_FUNCTION_ARGS)
Datum sha224_bytea(PG_FUNCTION_ARGS)
Datum md5_text(PG_FUNCTION_ARGS)
static bytea * cryptohash_internal(pg_cryptohash_type type, bytea *input)
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
FILE * input
void * palloc0(Size size)
Definition: mcxt.c:1346
bool pg_md5_hash(const void *buff, size_t len, char *hexsum, const char **errstr)
Definition: md5_common.c:74
const void size_t len
const void * data
uintptr_t Datum
Definition: postgres.h:64
#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
Definition: c.h:687
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
text * cstring_to_text(const char *s)
Definition: varlena.c:184
const char * type