PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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/backend_random.h"
38 #include "utils/builtins.h"
39 #include "utils/uuid.h"
40 
41 #include "px.h"
42 #include "px-crypt.h"
43 #include "pgcrypto.h"
44 
46 
47 /* private stuff */
48 
49 typedef int (*PFN) (const char *name, void **res);
50 static void *find_provider(text *name, PFN pf, char *desc, 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 
65  name = PG_GETARG_TEXT_P(1);
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 
75  arg = PG_GETARG_BYTEA_P(0);
76  len = VARSIZE(arg) - VARHDRSZ;
77 
78  px_md_update(md, (uint8 *) VARDATA(arg), len);
79  px_md_finish(md, (uint8 *) VARDATA(res));
80  px_md_free(md);
81 
82  PG_FREE_IF_COPY(arg, 0);
83  PG_FREE_IF_COPY(name, 1);
84 
85  PG_RETURN_BYTEA_P(res);
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_P(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_P(0);
114  key = PG_GETARG_BYTEA_P(1);
115  len = VARSIZE(arg) - VARHDRSZ;
116  klen = VARSIZE(key) - VARHDRSZ;
117 
118  px_hmac_init(h, (uint8 *) VARDATA(key), klen);
119  px_hmac_update(h, (uint8 *) VARDATA(arg), len);
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 
127  PG_RETURN_BYTEA_P(res);
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 
212  PG_RETURN_TEXT_P(res);
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_P(2);
232  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
233 
234  data = PG_GETARG_BYTEA_P(0);
235  key = PG_GETARG_BYTEA_P(1);
236  dlen = VARSIZE(data) - VARHDRSZ;
237  klen = VARSIZE(key) - VARHDRSZ;
238 
239  rlen = px_combo_encrypt_len(c, dlen);
240  res = palloc(VARHDRSZ + rlen);
241 
242  err = px_combo_init(c, (uint8 *) VARDATA(key), klen, NULL, 0);
243  if (!err)
244  err = px_combo_encrypt(c, (uint8 *) VARDATA(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);
261  PG_RETURN_BYTEA_P(res);
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_P(2);
281  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
282 
283  data = PG_GETARG_BYTEA_P(0);
284  key = PG_GETARG_BYTEA_P(1);
285  dlen = VARSIZE(data) - VARHDRSZ;
286  klen = VARSIZE(key) - VARHDRSZ;
287 
288  rlen = px_combo_decrypt_len(c, dlen);
289  res = palloc(VARHDRSZ + rlen);
290 
291  err = px_combo_init(c, (uint8 *) VARDATA(key), klen, NULL, 0);
292  if (!err)
293  err = px_combo_decrypt(c, (uint8 *) VARDATA(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 
309  PG_RETURN_BYTEA_P(res);
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_P(3);
331  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
332 
333  data = PG_GETARG_BYTEA_P(0);
334  key = PG_GETARG_BYTEA_P(1);
335  iv = PG_GETARG_BYTEA_P(2);
336  dlen = VARSIZE(data) - VARHDRSZ;
337  klen = VARSIZE(key) - VARHDRSZ;
338  ivlen = VARSIZE(iv) - VARHDRSZ;
339 
340  rlen = px_combo_encrypt_len(c, dlen);
341  res = palloc(VARHDRSZ + rlen);
342 
343  err = px_combo_init(c, (uint8 *) VARDATA(key), klen,
344  (uint8 *) VARDATA(iv), ivlen);
345  if (!err)
346  err = px_combo_encrypt(c, (uint8 *) VARDATA(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 
363  PG_RETURN_BYTEA_P(res);
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_P(3);
385  c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
386 
387  data = PG_GETARG_BYTEA_P(0);
388  key = PG_GETARG_BYTEA_P(1);
389  iv = PG_GETARG_BYTEA_P(2);
390  dlen = VARSIZE(data) - VARHDRSZ;
391  klen = VARSIZE(key) - VARHDRSZ;
392  ivlen = VARSIZE(iv) - VARHDRSZ;
393 
394  rlen = px_combo_decrypt_len(c, dlen);
395  res = palloc(VARHDRSZ + rlen);
396 
397  err = px_combo_init(c, (uint8 *) VARDATA(key), klen,
398  (uint8 *) VARDATA(iv), ivlen);
399  if (!err)
400  err = px_combo_decrypt(c, (uint8 *) VARDATA(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 
417  PG_RETURN_BYTEA_P(res);
418 }
419 
420 /* SQL function: pg_random_bytes(int4) returns bytea */
422 
423 Datum
425 {
426 #ifdef HAVE_STRONG_RANDOM
427  int len = PG_GETARG_INT32(0);
428  bytea *res;
429 
430  if (len < 1 || len > 1024)
431  ereport(ERROR,
432  (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
433  errmsg("Length not in range")));
434 
435  res = palloc(VARHDRSZ + len);
436  SET_VARSIZE(res, VARHDRSZ + len);
437 
438  /* generate result */
439  if (!pg_strong_random(VARDATA(res), len))
441 
442  PG_RETURN_BYTEA_P(res);
443 #else
445 #endif
446 }
447 
448 /* SQL function: gen_random_uuid() returns uuid */
450 
451 Datum
453 {
454  uint8 *buf = (uint8 *) palloc(UUID_LEN);
455 
456  /*
457  * Generate random bits. pg_backend_random() will do here, we don't
458  * promis UUIDs to be cryptographically random, when built with
459  * --disable-strong-random.
460  */
461  if (!pg_backend_random((char *) buf, UUID_LEN))
463 
464  /*
465  * Set magic numbers for a "version 4" (pseudorandom) UUID, see
466  * http://tools.ietf.org/html/rfc4122#section-4.4
467  */
468  buf[6] = (buf[6] & 0x0f) | 0x40; /* "version" field */
469  buf[8] = (buf[8] & 0x3f) | 0x80; /* "variant" field */
470 
471  PG_RETURN_UUID_P((pg_uuid_t *) buf);
472 }
473 
474 static void *
476  PFN provider_lookup,
477  char *desc, int silent)
478 {
479  void *res;
480  char *buf;
481  int err;
482 
484  VARSIZE(name) - VARHDRSZ,
485  false);
486 
487  err = provider_lookup(buf, &res);
488 
489  if (err && !silent)
490  ereport(ERROR,
491  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
492  errmsg("Cannot use \"%s\": %s", buf, px_strerror(err))));
493 
494  pfree(buf);
495 
496  return err ? NULL : res;
497 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
Datum pg_gen_salt_rounds(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:157
void px_THROW_ERROR(int err)
Definition: px.c:96
Datum pg_encrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:316
#define VARDATA(PTR)
Definition: postgres.h:305
#define VARSIZE(PTR)
Definition: postgres.h:306
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:131
static void * find_provider(text *name, PFN pf, char *desc, int silent)
Definition: pgcrypto.c:475
#define VARHDRSZ
Definition: c.h:441
#define px_combo_free(c)
Definition: px.h:241
#define px_md_update(md, data, dlen)
Definition: px.h:209
unsigned char uint8
Definition: c.h:263
Definition: px.h:170
bool pg_strong_random(void *buf, size_t len)
int errcode(int sqlerrcode)
Definition: elog.c:575
#define px_hmac_finish(hmac, buf)
Definition: px.h:218
#define PXE_NO_RANDOM
Definition: px.h:79
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:313
Datum pg_random_bytes(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:424
#define px_md_finish(md, buf)
Definition: px.h:210
#define px_combo_encrypt_len(c, dlen)
Definition: px.h:233
void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len)
Definition: varlena.c:215
#define PX_MAX_SALT_LEN
Definition: px-crypt.h:39
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
Datum pg_crypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:180
#define PG_GETARG_BYTEA_P(n)
Definition: fmgr.h:267
void pfree(void *pointer)
Definition: mcxt.c:992
#define px_md_result_size(md)
Definition: px.h:206
#define ERROR
Definition: elog.h:43
#define px_combo_decrypt_len(c, dlen)
Definition: px.h:234
Definition: px.h:114
#define px_combo_encrypt(c, data, dlen, res, rlen)
Definition: px.h:237
int(* PFN)(const char *name, void **res)
Definition: pgcrypto.c:49
char * c
bool pg_backend_random(char *dst, int len)
static char * buf
Definition: pg_test_fsync.c:65
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:163
int px_gen_salt(const char *salt_type, char *buf, int rounds)
Definition: px-crypt.c:134
int px_find_combo(const char *name, PX_Combo **res)
Definition: px.c:410
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_RETURN_UUID_P(X)
Definition: uuid.h:27
#define px_hmac_init(hmac, key, klen)
Definition: px.h:216
const char * px_strerror(int err)
Definition: px.c:122
PG_MODULE_MAGIC
Definition: pgcrypto.c:45
#define px_md_free(md)
Definition: px.h:211
#define UUID_LEN
Definition: uuid.h:18
void * palloc0(Size size)
Definition: mcxt.c:920
uintptr_t Datum
Definition: postgres.h:374
Datum pg_gen_salt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:135
#define px_combo_decrypt(c, data, dlen, res, rlen)
Definition: px.h:239
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
text * cstring_to_text(const char *s)
Definition: varlena.c:151
Datum pg_random_uuid(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:452
#define NULL
Definition: c.h:226
Datum pg_encrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:219
Datum pg_digest(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:56
Datum pg_decrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:268
PG_FUNCTION_INFO_V1(pg_digest)
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:216
#define px_hmac_update(hmac, data, dlen)
Definition: px.h:217
const char * name
Definition: encode.c:521
Datum pg_hmac(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:92
Datum pg_decrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:370
char * text_to_cstring(const text *t)
Definition: varlena.c:184
Definition: uuid.h:20
#define PX_MAX_CRYPT
Definition: px-crypt.h:36
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
#define px_combo_init(c, key, klen, iv, ivlen)
Definition: px.h:235
void * arg
Definition: c.h:435
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
#define px_hmac_result_size(hmac)
Definition: px.h:213
char * px_crypt(const char *psw, const char *salt, char *buf, unsigned len)
Definition: px-crypt.c:92
Definition: px.h:136
int px_find_digest(const char *name, PX_MD **res)
Definition: internal.c:578
#define px_hmac_free(hmac)
Definition: px.h:219