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 "pgcrypto.h"
38 #include "px-crypt.h"
39 #include "px.h"
40 #include "utils/builtins.h"
41 #include "utils/uuid.h"
42 
44 
45 /* private stuff */
46 
47 typedef int (*PFN) (const char *name, void **res);
48 static void *find_provider(text *name, PFN pf, const char *desc, int silent);
49 
50 /* SQL function: hash(bytea, text) returns bytea */
52 
53 Datum
55 {
56  bytea *arg;
57  text *name;
58  unsigned len,
59  hlen;
60  PX_MD *md;
61  bytea *res;
62 
63  name = PG_GETARG_TEXT_PP(1);
64 
65  /* will give error if fails */
66  md = find_provider(name, (PFN) px_find_digest, "Digest", 0);
67 
68  hlen = px_md_result_size(md);
69 
70  res = (text *) palloc(hlen + VARHDRSZ);
71  SET_VARSIZE(res, hlen + VARHDRSZ);
72 
73  arg = PG_GETARG_BYTEA_PP(0);
74  len = VARSIZE_ANY_EXHDR(arg);
75 
76  px_md_update(md, (uint8 *) VARDATA_ANY(arg), len);
77  px_md_finish(md, (uint8 *) VARDATA(res));
78  px_md_free(md);
79 
80  PG_FREE_IF_COPY(arg, 0);
81  PG_FREE_IF_COPY(name, 1);
82 
83  PG_RETURN_BYTEA_P(res);
84 }
85 
86 /* SQL function: hmac(data:bytea, key:bytea, type:text) returns bytea */
88 
89 Datum
91 {
92  bytea *arg;
93  bytea *key;
94  text *name;
95  unsigned len,
96  hlen,
97  klen;
98  PX_HMAC *h;
99  bytea *res;
100 
101  name = PG_GETARG_TEXT_PP(2);
102 
103  /* will give error if fails */
104  h = find_provider(name, (PFN) px_find_hmac, "HMAC", 0);
105 
106  hlen = px_hmac_result_size(h);
107 
108  res = (text *) palloc(hlen + VARHDRSZ);
109  SET_VARSIZE(res, hlen + VARHDRSZ);
110 
111  arg = PG_GETARG_BYTEA_PP(0);
112  key = PG_GETARG_BYTEA_PP(1);
113  len = VARSIZE_ANY_EXHDR(arg);
114  klen = VARSIZE_ANY_EXHDR(key);
115 
116  px_hmac_init(h, (uint8 *) VARDATA_ANY(key), klen);
117  px_hmac_update(h, (uint8 *) VARDATA_ANY(arg), len);
118  px_hmac_finish(h, (uint8 *) VARDATA(res));
119  px_hmac_free(h);
120 
121  PG_FREE_IF_COPY(arg, 0);
122  PG_FREE_IF_COPY(key, 1);
123  PG_FREE_IF_COPY(name, 2);
124 
125  PG_RETURN_BYTEA_P(res);
126 }
127 
128 
129 /* SQL function: pg_gen_salt(text) returns text */
131 
132 Datum
134 {
135  text *arg0 = PG_GETARG_TEXT_PP(0);
136  int len;
137  char buf[PX_MAX_SALT_LEN + 1];
138 
139  text_to_cstring_buffer(arg0, buf, sizeof(buf));
140  len = px_gen_salt(buf, buf, 0);
141  if (len < 0)
142  ereport(ERROR,
143  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
144  errmsg("gen_salt: %s", px_strerror(len))));
145 
146  PG_FREE_IF_COPY(arg0, 0);
147 
149 }
150 
151 /* SQL function: pg_gen_salt(text, int4) returns text */
153 
154 Datum
156 {
157  text *arg0 = PG_GETARG_TEXT_PP(0);
158  int rounds = PG_GETARG_INT32(1);
159  int len;
160  char buf[PX_MAX_SALT_LEN + 1];
161 
162  text_to_cstring_buffer(arg0, buf, sizeof(buf));
163  len = px_gen_salt(buf, buf, rounds);
164  if (len < 0)
165  ereport(ERROR,
166  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
167  errmsg("gen_salt: %s", px_strerror(len))));
168 
169  PG_FREE_IF_COPY(arg0, 0);
170 
172 }
173 
174 /* SQL function: pg_crypt(psw:text, salt:text) returns text */
176 
177 Datum
179 {
180  text *arg0 = PG_GETARG_TEXT_PP(0);
181  text *arg1 = PG_GETARG_TEXT_PP(1);
182  char *buf0,
183  *buf1,
184  *cres,
185  *resbuf;
186  text *res;
187 
188  buf0 = text_to_cstring(arg0);
189  buf1 = text_to_cstring(arg1);
190 
191  resbuf = palloc0(PX_MAX_CRYPT);
192 
193  cres = px_crypt(buf0, buf1, resbuf, PX_MAX_CRYPT);
194 
195  pfree(buf0);
196  pfree(buf1);
197 
198  if (cres == NULL)
199  ereport(ERROR,
200  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
201  errmsg("crypt(3) returned NULL")));
202 
203  res = cstring_to_text(cres);
204 
205  pfree(resbuf);
206 
207  PG_FREE_IF_COPY(arg0, 0);
208  PG_FREE_IF_COPY(arg1, 1);
209 
210  PG_RETURN_TEXT_P(res);
211 }
212 
213 /* SQL function: pg_encrypt(bytea, bytea, text) returns bytea */
215 
216 Datum
218 {
219  int err;
220  bytea *data,
221  *key,
222  *res;
223  text *type;
224  PX_Combo *c;
225  unsigned dlen,
226  klen,
227  rlen;
228 
229  type = PG_GETARG_TEXT_PP(2);
230  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
231 
232  data = PG_GETARG_BYTEA_PP(0);
233  key = PG_GETARG_BYTEA_PP(1);
234  dlen = VARSIZE_ANY_EXHDR(data);
235  klen = VARSIZE_ANY_EXHDR(key);
236 
237  rlen = px_combo_encrypt_len(c, dlen);
238  res = palloc(VARHDRSZ + rlen);
239 
240  err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen, NULL, 0);
241  if (!err)
242  err = px_combo_encrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
243  (uint8 *) VARDATA(res), &rlen);
244  px_combo_free(c);
245 
246  PG_FREE_IF_COPY(data, 0);
247  PG_FREE_IF_COPY(key, 1);
248  PG_FREE_IF_COPY(type, 2);
249 
250  if (err)
251  {
252  pfree(res);
253  ereport(ERROR,
254  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
255  errmsg("encrypt error: %s", px_strerror(err))));
256  }
257 
258  SET_VARSIZE(res, VARHDRSZ + rlen);
259  PG_RETURN_BYTEA_P(res);
260 }
261 
262 /* SQL function: pg_decrypt(bytea, bytea, text) returns bytea */
264 
265 Datum
267 {
268  int err;
269  bytea *data,
270  *key,
271  *res;
272  text *type;
273  PX_Combo *c;
274  unsigned dlen,
275  klen,
276  rlen;
277 
278  type = PG_GETARG_TEXT_PP(2);
279  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
280 
281  data = PG_GETARG_BYTEA_PP(0);
282  key = PG_GETARG_BYTEA_PP(1);
283  dlen = VARSIZE_ANY_EXHDR(data);
284  klen = VARSIZE_ANY_EXHDR(key);
285 
286  rlen = px_combo_decrypt_len(c, dlen);
287  res = palloc(VARHDRSZ + rlen);
288 
289  err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen, NULL, 0);
290  if (!err)
291  err = px_combo_decrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
292  (uint8 *) VARDATA(res), &rlen);
293 
294  px_combo_free(c);
295 
296  if (err)
297  ereport(ERROR,
298  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
299  errmsg("decrypt error: %s", px_strerror(err))));
300 
301  SET_VARSIZE(res, VARHDRSZ + rlen);
302 
303  PG_FREE_IF_COPY(data, 0);
304  PG_FREE_IF_COPY(key, 1);
305  PG_FREE_IF_COPY(type, 2);
306 
307  PG_RETURN_BYTEA_P(res);
308 }
309 
310 /* SQL function: pg_encrypt_iv(bytea, bytea, bytea, text) returns bytea */
312 
313 Datum
315 {
316  int err;
317  bytea *data,
318  *key,
319  *iv,
320  *res;
321  text *type;
322  PX_Combo *c;
323  unsigned dlen,
324  klen,
325  ivlen,
326  rlen;
327 
328  type = PG_GETARG_TEXT_PP(3);
329  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
330 
331  data = PG_GETARG_BYTEA_PP(0);
332  key = PG_GETARG_BYTEA_PP(1);
333  iv = PG_GETARG_BYTEA_PP(2);
334  dlen = VARSIZE_ANY_EXHDR(data);
335  klen = VARSIZE_ANY_EXHDR(key);
336  ivlen = VARSIZE_ANY_EXHDR(iv);
337 
338  rlen = px_combo_encrypt_len(c, dlen);
339  res = palloc(VARHDRSZ + rlen);
340 
341  err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen,
342  (uint8 *) VARDATA_ANY(iv), ivlen);
343  if (!err)
344  err = px_combo_encrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
345  (uint8 *) VARDATA(res), &rlen);
346 
347  px_combo_free(c);
348 
349  if (err)
350  ereport(ERROR,
351  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
352  errmsg("encrypt_iv error: %s", px_strerror(err))));
353 
354  SET_VARSIZE(res, VARHDRSZ + rlen);
355 
356  PG_FREE_IF_COPY(data, 0);
357  PG_FREE_IF_COPY(key, 1);
358  PG_FREE_IF_COPY(iv, 2);
359  PG_FREE_IF_COPY(type, 3);
360 
361  PG_RETURN_BYTEA_P(res);
362 }
363 
364 /* SQL function: pg_decrypt_iv(bytea, bytea, bytea, text) returns bytea */
366 
367 Datum
369 {
370  int err;
371  bytea *data,
372  *key,
373  *iv,
374  *res;
375  text *type;
376  PX_Combo *c;
377  unsigned dlen,
378  klen,
379  rlen,
380  ivlen;
381 
382  type = PG_GETARG_TEXT_PP(3);
383  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
384 
385  data = PG_GETARG_BYTEA_PP(0);
386  key = PG_GETARG_BYTEA_PP(1);
387  iv = PG_GETARG_BYTEA_PP(2);
388  dlen = VARSIZE_ANY_EXHDR(data);
389  klen = VARSIZE_ANY_EXHDR(key);
390  ivlen = VARSIZE_ANY_EXHDR(iv);
391 
392  rlen = px_combo_decrypt_len(c, dlen);
393  res = palloc(VARHDRSZ + rlen);
394 
395  err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen,
396  (uint8 *) VARDATA_ANY(iv), ivlen);
397  if (!err)
398  err = px_combo_decrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
399  (uint8 *) VARDATA(res), &rlen);
400 
401  px_combo_free(c);
402 
403  if (err)
404  ereport(ERROR,
405  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
406  errmsg("decrypt_iv error: %s", px_strerror(err))));
407 
408  SET_VARSIZE(res, VARHDRSZ + rlen);
409 
410  PG_FREE_IF_COPY(data, 0);
411  PG_FREE_IF_COPY(key, 1);
412  PG_FREE_IF_COPY(iv, 2);
413  PG_FREE_IF_COPY(type, 3);
414 
415  PG_RETURN_BYTEA_P(res);
416 }
417 
418 /* SQL function: pg_random_bytes(int4) returns bytea */
420 
421 Datum
423 {
424  int len = PG_GETARG_INT32(0);
425  bytea *res;
426 
427  if (len < 1 || len > 1024)
428  ereport(ERROR,
429  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
430  errmsg("Length not in range")));
431 
432  res = palloc(VARHDRSZ + len);
433  SET_VARSIZE(res, VARHDRSZ + len);
434 
435  /* generate result */
436  if (!pg_strong_random(VARDATA(res), len))
438 
439  PG_RETURN_BYTEA_P(res);
440 }
441 
442 /* SQL function: gen_random_uuid() returns uuid */
444 
445 Datum
447 {
448  /* redirect to built-in function */
449  return gen_random_uuid(fcinfo);
450 }
451 
452 static void *
454  PFN provider_lookup,
455  const char *desc, int silent)
456 {
457  void *res;
458  char *buf;
459  int err;
460 
462  VARSIZE_ANY_EXHDR(name),
463  false);
464 
465  err = provider_lookup(buf, &res);
466 
467  if (err && !silent)
468  ereport(ERROR,
469  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
470  errmsg("Cannot use \"%s\": %s", buf, px_strerror(err))));
471 
472  pfree(buf);
473 
474  return err ? NULL : res;
475 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
Datum pg_gen_salt_rounds(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:155
void px_THROW_ERROR(int err)
Definition: px.c:96
Datum pg_encrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:314
#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:47
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:130
#define VARHDRSZ
Definition: c.h:562
#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:357
Definition: px.h:166
int errcode(int sqlerrcode)
Definition: elog.c:608
#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:422
#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:178
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:67
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:132
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:43
#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:133
#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:446
Datum pg_encrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:217
Datum pg_digest(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:54
Datum pg_decrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:266
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:453
#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:90
Datum pg_decrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:368
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:822
#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:556
#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:90
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