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 "varatt.h"
42 
44 
45 /* private stuff */
46 
47 typedef int (*PFN) (const char *name, void **res);
48 static void *find_provider(text *name, PFN provider_lookup, const char *desc,
49  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 
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 
76 
78  px_md_finish(md, (uint8 *) VARDATA(res));
79  px_md_free(md);
80 
81  PG_FREE_IF_COPY(arg, 0);
83 
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);
115  klen = VARSIZE_ANY_EXHDR(key);
116 
117  px_hmac_init(h, (uint8 *) VARDATA_ANY(key), klen);
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 
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 
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 
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);
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 
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 
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 
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 
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 
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 
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);
435 
436  /* generate result */
439 
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 
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 }
uint8_t uint8
Definition: c.h:483
#define VARHDRSZ
Definition: c.h:646
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void err(int eval, const char *fmt,...)
Definition: err.c:43
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#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_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
int px_find_digest(const char *name, PX_MD **res)
Definition: openssl.c:160
void * arg
const void size_t len
const void * data
static char * buf
Definition: pg_test_fsync.c:72
Datum pg_encrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:315
Datum pg_encrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:218
static void * find_provider(text *name, PFN provider_lookup, const char *desc, int silent)
Definition: pgcrypto.c:454
PG_MODULE_MAGIC
Definition: pgcrypto.c:43
Datum pg_gen_salt_rounds(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:156
Datum pg_decrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:369
Datum pg_random_uuid(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:447
Datum pg_hmac(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:91
Datum pg_crypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:179
int(* PFN)(const char *name, void **res)
Definition: pgcrypto.c:47
Datum pg_random_bytes(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:423
PG_FUNCTION_INFO_V1(pg_digest)
Datum pg_gen_salt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:134
Datum pg_digest(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:55
Datum pg_decrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:267
bool pg_strong_random(void *buf, size_t len)
uintptr_t Datum
Definition: postgres.h:64
char * c
int px_gen_salt(const char *salt_type, char *buf, int rounds)
Definition: px-crypt.c:132
char * px_crypt(const char *psw, const char *salt, char *buf, unsigned len)
Definition: px-crypt.c:90
#define PX_MAX_SALT_LEN
Definition: px-crypt.h:39
#define PX_MAX_CRYPT
Definition: px-crypt.h:36
int px_find_hmac(const char *name, PX_HMAC **res)
Definition: px-hmac.c:142
void px_THROW_ERROR(int err)
Definition: px.c:93
const char * px_strerror(int err)
Definition: px.c:111
int px_find_combo(const char *name, PX_Combo **res)
Definition: px.c:285
#define px_md_finish(md, buf)
Definition: px.h:195
#define px_combo_init(c, key, klen, iv, ivlen)
Definition: px.h:220
#define px_hmac_result_size(hmac)
Definition: px.h:198
#define px_hmac_finish(hmac, buf)
Definition: px.h:203
#define px_combo_encrypt_len(c, dlen)
Definition: px.h:218
#define px_md_free(md)
Definition: px.h:196
#define px_hmac_update(hmac, data, dlen)
Definition: px.h:202
#define px_hmac_init(hmac, key, klen)
Definition: px.h:201
#define px_combo_encrypt(c, data, dlen, res, rlen)
Definition: px.h:222
#define px_hmac_free(hmac)
Definition: px.h:204
#define px_combo_decrypt_len(c, dlen)
Definition: px.h:219
#define px_combo_free(c)
Definition: px.h:226
#define px_combo_decrypt(c, data, dlen, res, rlen)
Definition: px.h:224
#define PXE_NO_RANDOM
Definition: px.h:63
#define px_md_update(md, data, dlen)
Definition: px.h:194
#define px_md_result_size(md)
Definition: px.h:191
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:37
Definition: px.h:156
Definition: px.h:100
Definition: px.h:122
Definition: c.h:641
Datum gen_random_uuid(PG_FUNCTION_ARGS)
Definition: uuid.c:405
#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
char * text_to_cstring(const text *t)
Definition: varlena.c:217
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196
void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len)
Definition: varlena.c:248
text * cstring_to_text(const char *s)
Definition: varlena.c:184
const char * type
const char * name