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