PostgreSQL Source Code  git master
pgcrypto.c
Go to the documentation of this file.
1 /*
2  * pgcrypto.c
3  * Various cryptographic stuff for PostgreSQL.
4  *
5  * Copyright (c) 2001 Marko Kreen
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * contrib/pgcrypto/pgcrypto.c
30  */
31 
32 #include "postgres.h"
33 
34 #include <ctype.h>
35 
36 #include "parser/scansup.h"
37 #include "utils/builtins.h"
38 #include "utils/uuid.h"
39 
40 #include "px.h"
41 #include "px-crypt.h"
42 #include "pgcrypto.h"
43 
45 
46 /* private stuff */
47 
48 typedef int (*PFN) (const char *name, void **res);
49 static void *find_provider(text *name, PFN pf, const char *desc, int silent);
50 
51 /* SQL function: hash(bytea, text) returns bytea */
53 
54 Datum
56 {
57  bytea *arg;
58  text *name;
59  unsigned len,
60  hlen;
61  PX_MD *md;
62  bytea *res;
63 
64  name = PG_GETARG_TEXT_PP(1);
65 
66  /* will give error if fails */
67  md = find_provider(name, (PFN) px_find_digest, "Digest", 0);
68 
69  hlen = px_md_result_size(md);
70 
71  res = (text *) palloc(hlen + VARHDRSZ);
72  SET_VARSIZE(res, hlen + VARHDRSZ);
73 
74  arg = PG_GETARG_BYTEA_PP(0);
75  len = VARSIZE_ANY_EXHDR(arg);
76 
77  px_md_update(md, (uint8 *) VARDATA_ANY(arg), len);
78  px_md_finish(md, (uint8 *) VARDATA(res));
79  px_md_free(md);
80 
81  PG_FREE_IF_COPY(arg, 0);
82  PG_FREE_IF_COPY(name, 1);
83 
84  PG_RETURN_BYTEA_P(res);
85 }
86 
87 /* SQL function: hmac(data:bytea, key:bytea, type:text) returns bytea */
89 
90 Datum
92 {
93  bytea *arg;
94  bytea *key;
95  text *name;
96  unsigned len,
97  hlen,
98  klen;
99  PX_HMAC *h;
100  bytea *res;
101 
102  name = PG_GETARG_TEXT_PP(2);
103 
104  /* will give error if fails */
105  h = find_provider(name, (PFN) px_find_hmac, "HMAC", 0);
106 
107  hlen = px_hmac_result_size(h);
108 
109  res = (text *) palloc(hlen + VARHDRSZ);
110  SET_VARSIZE(res, hlen + VARHDRSZ);
111 
112  arg = PG_GETARG_BYTEA_PP(0);
113  key = PG_GETARG_BYTEA_PP(1);
114  len = VARSIZE_ANY_EXHDR(arg);
115  klen = VARSIZE_ANY_EXHDR(key);
116 
117  px_hmac_init(h, (uint8 *) VARDATA_ANY(key), klen);
118  px_hmac_update(h, (uint8 *) VARDATA_ANY(arg), len);
119  px_hmac_finish(h, (uint8 *) VARDATA(res));
120  px_hmac_free(h);
121 
122  PG_FREE_IF_COPY(arg, 0);
123  PG_FREE_IF_COPY(key, 1);
124  PG_FREE_IF_COPY(name, 2);
125 
126  PG_RETURN_BYTEA_P(res);
127 }
128 
129 
130 /* SQL function: pg_gen_salt(text) returns text */
132 
133 Datum
135 {
136  text *arg0 = PG_GETARG_TEXT_PP(0);
137  int len;
138  char buf[PX_MAX_SALT_LEN + 1];
139 
140  text_to_cstring_buffer(arg0, buf, sizeof(buf));
141  len = px_gen_salt(buf, buf, 0);
142  if (len < 0)
143  ereport(ERROR,
144  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
145  errmsg("gen_salt: %s", px_strerror(len))));
146 
147  PG_FREE_IF_COPY(arg0, 0);
148 
150 }
151 
152 /* SQL function: pg_gen_salt(text, int4) returns text */
154 
155 Datum
157 {
158  text *arg0 = PG_GETARG_TEXT_PP(0);
159  int rounds = PG_GETARG_INT32(1);
160  int len;
161  char buf[PX_MAX_SALT_LEN + 1];
162 
163  text_to_cstring_buffer(arg0, buf, sizeof(buf));
164  len = px_gen_salt(buf, buf, rounds);
165  if (len < 0)
166  ereport(ERROR,
167  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
168  errmsg("gen_salt: %s", px_strerror(len))));
169 
170  PG_FREE_IF_COPY(arg0, 0);
171 
173 }
174 
175 /* SQL function: pg_crypt(psw:text, salt:text) returns text */
177 
178 Datum
180 {
181  text *arg0 = PG_GETARG_TEXT_PP(0);
182  text *arg1 = PG_GETARG_TEXT_PP(1);
183  char *buf0,
184  *buf1,
185  *cres,
186  *resbuf;
187  text *res;
188 
189  buf0 = text_to_cstring(arg0);
190  buf1 = text_to_cstring(arg1);
191 
192  resbuf = palloc0(PX_MAX_CRYPT);
193 
194  cres = px_crypt(buf0, buf1, resbuf, PX_MAX_CRYPT);
195 
196  pfree(buf0);
197  pfree(buf1);
198 
199  if (cres == NULL)
200  ereport(ERROR,
201  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
202  errmsg("crypt(3) returned NULL")));
203 
204  res = cstring_to_text(cres);
205 
206  pfree(resbuf);
207 
208  PG_FREE_IF_COPY(arg0, 0);
209  PG_FREE_IF_COPY(arg1, 1);
210 
211  PG_RETURN_TEXT_P(res);
212 }
213 
214 /* SQL function: pg_encrypt(bytea, bytea, text) returns bytea */
216 
217 Datum
219 {
220  int err;
221  bytea *data,
222  *key,
223  *res;
224  text *type;
225  PX_Combo *c;
226  unsigned dlen,
227  klen,
228  rlen;
229 
230  type = PG_GETARG_TEXT_PP(2);
231  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
232 
233  data = PG_GETARG_BYTEA_PP(0);
234  key = PG_GETARG_BYTEA_PP(1);
235  dlen = VARSIZE_ANY_EXHDR(data);
236  klen = VARSIZE_ANY_EXHDR(key);
237 
238  rlen = px_combo_encrypt_len(c, dlen);
239  res = palloc(VARHDRSZ + rlen);
240 
241  err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen, NULL, 0);
242  if (!err)
243  err = px_combo_encrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
244  (uint8 *) VARDATA(res), &rlen);
245  px_combo_free(c);
246 
247  PG_FREE_IF_COPY(data, 0);
248  PG_FREE_IF_COPY(key, 1);
249  PG_FREE_IF_COPY(type, 2);
250 
251  if (err)
252  {
253  pfree(res);
254  ereport(ERROR,
255  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
256  errmsg("encrypt error: %s", px_strerror(err))));
257  }
258 
259  SET_VARSIZE(res, VARHDRSZ + rlen);
260  PG_RETURN_BYTEA_P(res);
261 }
262 
263 /* SQL function: pg_decrypt(bytea, bytea, text) returns bytea */
265 
266 Datum
268 {
269  int err;
270  bytea *data,
271  *key,
272  *res;
273  text *type;
274  PX_Combo *c;
275  unsigned dlen,
276  klen,
277  rlen;
278 
279  type = PG_GETARG_TEXT_PP(2);
280  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
281 
282  data = PG_GETARG_BYTEA_PP(0);
283  key = PG_GETARG_BYTEA_PP(1);
284  dlen = VARSIZE_ANY_EXHDR(data);
285  klen = VARSIZE_ANY_EXHDR(key);
286 
287  rlen = px_combo_decrypt_len(c, dlen);
288  res = palloc(VARHDRSZ + rlen);
289 
290  err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen, NULL, 0);
291  if (!err)
292  err = px_combo_decrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
293  (uint8 *) VARDATA(res), &rlen);
294 
295  px_combo_free(c);
296 
297  if (err)
298  ereport(ERROR,
299  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
300  errmsg("decrypt error: %s", px_strerror(err))));
301 
302  SET_VARSIZE(res, VARHDRSZ + rlen);
303 
304  PG_FREE_IF_COPY(data, 0);
305  PG_FREE_IF_COPY(key, 1);
306  PG_FREE_IF_COPY(type, 2);
307 
308  PG_RETURN_BYTEA_P(res);
309 }
310 
311 /* SQL function: pg_encrypt_iv(bytea, bytea, bytea, text) returns bytea */
313 
314 Datum
316 {
317  int err;
318  bytea *data,
319  *key,
320  *iv,
321  *res;
322  text *type;
323  PX_Combo *c;
324  unsigned dlen,
325  klen,
326  ivlen,
327  rlen;
328 
329  type = PG_GETARG_TEXT_PP(3);
330  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
331 
332  data = PG_GETARG_BYTEA_PP(0);
333  key = PG_GETARG_BYTEA_PP(1);
334  iv = PG_GETARG_BYTEA_PP(2);
335  dlen = VARSIZE_ANY_EXHDR(data);
336  klen = VARSIZE_ANY_EXHDR(key);
337  ivlen = VARSIZE_ANY_EXHDR(iv);
338 
339  rlen = px_combo_encrypt_len(c, dlen);
340  res = palloc(VARHDRSZ + rlen);
341 
342  err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen,
343  (uint8 *) VARDATA_ANY(iv), ivlen);
344  if (!err)
345  err = px_combo_encrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
346  (uint8 *) VARDATA(res), &rlen);
347 
348  px_combo_free(c);
349 
350  if (err)
351  ereport(ERROR,
352  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
353  errmsg("encrypt_iv error: %s", px_strerror(err))));
354 
355  SET_VARSIZE(res, VARHDRSZ + rlen);
356 
357  PG_FREE_IF_COPY(data, 0);
358  PG_FREE_IF_COPY(key, 1);
359  PG_FREE_IF_COPY(iv, 2);
360  PG_FREE_IF_COPY(type, 3);
361 
362  PG_RETURN_BYTEA_P(res);
363 }
364 
365 /* SQL function: pg_decrypt_iv(bytea, bytea, bytea, text) returns bytea */
367 
368 Datum
370 {
371  int err;
372  bytea *data,
373  *key,
374  *iv,
375  *res;
376  text *type;
377  PX_Combo *c;
378  unsigned dlen,
379  klen,
380  rlen,
381  ivlen;
382 
383  type = PG_GETARG_TEXT_PP(3);
384  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
385 
386  data = PG_GETARG_BYTEA_PP(0);
387  key = PG_GETARG_BYTEA_PP(1);
388  iv = PG_GETARG_BYTEA_PP(2);
389  dlen = VARSIZE_ANY_EXHDR(data);
390  klen = VARSIZE_ANY_EXHDR(key);
391  ivlen = VARSIZE_ANY_EXHDR(iv);
392 
393  rlen = px_combo_decrypt_len(c, dlen);
394  res = palloc(VARHDRSZ + rlen);
395 
396  err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen,
397  (uint8 *) VARDATA_ANY(iv), ivlen);
398  if (!err)
399  err = px_combo_decrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
400  (uint8 *) VARDATA(res), &rlen);
401 
402  px_combo_free(c);
403 
404  if (err)
405  ereport(ERROR,
406  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
407  errmsg("decrypt_iv error: %s", px_strerror(err))));
408 
409  SET_VARSIZE(res, VARHDRSZ + rlen);
410 
411  PG_FREE_IF_COPY(data, 0);
412  PG_FREE_IF_COPY(key, 1);
413  PG_FREE_IF_COPY(iv, 2);
414  PG_FREE_IF_COPY(type, 3);
415 
416  PG_RETURN_BYTEA_P(res);
417 }
418 
419 /* SQL function: pg_random_bytes(int4) returns bytea */
421 
422 Datum
424 {
425  int len = PG_GETARG_INT32(0);
426  bytea *res;
427 
428  if (len < 1 || len > 1024)
429  ereport(ERROR,
430  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
431  errmsg("Length not in range")));
432 
433  res = palloc(VARHDRSZ + len);
434  SET_VARSIZE(res, VARHDRSZ + len);
435 
436  /* generate result */
437  if (!pg_strong_random(VARDATA(res), len))
439 
440  PG_RETURN_BYTEA_P(res);
441 }
442 
443 /* SQL function: gen_random_uuid() returns uuid */
445 
446 Datum
448 {
449  /* redirect to built-in function */
450  return gen_random_uuid(fcinfo);
451 }
452 
453 static void *
455  PFN provider_lookup,
456  const char *desc, int silent)
457 {
458  void *res;
459  char *buf;
460  int err;
461 
463  VARSIZE_ANY_EXHDR(name),
464  false);
465 
466  err = provider_lookup(buf, &res);
467 
468  if (err && !silent)
469  ereport(ERROR,
470  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
471  errmsg("Cannot use \"%s\": %s", buf, px_strerror(err))));
472 
473  pfree(buf);
474 
475  return err ? NULL : res;
476 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
Datum pg_gen_salt_rounds(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:156
void px_THROW_ERROR(int err)
Definition: px.c:96
Datum pg_encrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:315
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
#define VARDATA(PTR)
Definition: postgres.h:302
int(* PFN)(const char *name, void **res)
Definition: pgcrypto.c:48
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:131
#define VARHDRSZ
Definition: c.h:555
#define px_combo_free(c)
Definition: px.h:237
#define px_md_update(md, data, dlen)
Definition: px.h:205
unsigned char uint8
Definition: c.h:356
Definition: px.h:166
int errcode(int sqlerrcode)
Definition: elog.c:570
#define px_hmac_finish(hmac, buf)
Definition: px.h:214
#define PXE_NO_RANDOM
Definition: px.h:75
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:360
Datum pg_random_bytes(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:423
#define px_md_finish(md, buf)
Definition: px.h:206
#define px_combo_encrypt_len(c, dlen)
Definition: px.h:229
void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len)
Definition: varlena.c:235
#define PX_MAX_SALT_LEN
Definition: px-crypt.h:39
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
Datum pg_crypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:179
void pfree(void *pointer)
Definition: mcxt.c:1056
#define px_md_result_size(md)
Definition: px.h:202
#define ERROR
Definition: elog.h:43
#define px_combo_decrypt_len(c, dlen)
Definition: px.h:230
Definition: px.h:110
#define px_combo_encrypt(c, data, dlen, res, rlen)
Definition: px.h:233
char * c
static char * buf
Definition: pg_test_fsync.c:68
int px_find_hmac(const char *name, PX_HMAC **res)
Definition: px-hmac.c:143
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
int px_gen_salt(const char *salt_type, char *buf, int rounds)
Definition: px-crypt.c:133
int px_find_combo(const char *name, PX_Combo **res)
Definition: px.c:402
#define ereport(elevel, rest)
Definition: elog.h:141
#define px_hmac_init(hmac, key, klen)
Definition: px.h:212
const char * px_strerror(int err)
Definition: px.c:114
PG_MODULE_MAGIC
Definition: pgcrypto.c:44
#define px_md_free(md)
Definition: px.h:207
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
Datum pg_gen_salt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:134
#define px_combo_decrypt(c, data, dlen, res, rlen)
Definition: px.h:235
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
bool pg_strong_random(void *buf, size_t len)
text * cstring_to_text(const char *s)
Definition: varlena.c:171
Datum pg_random_uuid(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:447
Datum pg_encrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:218
Datum pg_digest(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:55
Datum pg_decrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:267
PG_FUNCTION_INFO_V1(pg_digest)
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:302
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
static void * find_provider(text *name, PFN pf, const char *desc, int silent)
Definition: pgcrypto.c:454
#define px_hmac_update(hmac, data, dlen)
Definition: px.h:213
const char * name
Definition: encode.c:521
Datum pg_hmac(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:91
Datum pg_decrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:369
char * text_to_cstring(const text *t)
Definition: varlena.c:204
#define PX_MAX_CRYPT
Definition: px-crypt.h:36
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define px_combo_init(c, key, klen, iv, ivlen)
Definition: px.h:231
void * arg
Datum gen_random_uuid(PG_FUNCTION_ARGS)
Definition: uuid.c:421
Definition: c.h:549
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define px_hmac_result_size(hmac)
Definition: px.h:209
char * px_crypt(const char *psw, const char *salt, char *buf, unsigned len)
Definition: px-crypt.c:91
Definition: px.h:132
int px_find_digest(const char *name, PX_MD **res)
Definition: internal.c:559
#define px_hmac_free(hmac)
Definition: px.h:215