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/guc.h"
42#include "varatt.h"
43
45 .name = "pgcrypto",
46 .version = PG_VERSION
47);
48
49/* private stuff */
50
52 {"on", BC_ON, false},
53 {"off", BC_OFF, false},
54 {"fips", BC_FIPS, false},
55 {NULL, 0, false}
56};
57
58typedef int (*PFN) (const char *name, void **res);
59static void *find_provider(text *name, PFN provider_lookup, const char *desc,
60 int silent);
61
63
64/*
65 * Entrypoint of this module.
66 */
67void
69{
70 DefineCustomEnumVariable("pgcrypto.builtin_crypto_enabled",
71 "Sets if builtin crypto functions are enabled.",
72 "\"on\" enables builtin crypto, \"off\" unconditionally disables and \"fips\" "
73 "will disable builtin crypto if OpenSSL is in FIPS mode",
75 BC_ON,
78 0,
79 NULL,
80 NULL,
81 NULL);
82 MarkGUCPrefixReserved("pgcrypto");
83}
84
85/* SQL function: hash(bytea, text) returns bytea */
87
90{
91 bytea *arg;
92 text *name;
93 unsigned len,
94 hlen;
95 PX_MD *md;
96 bytea *res;
97
99
100 /* will give error if fails */
101 md = find_provider(name, (PFN) px_find_digest, "Digest", 0);
102
103 hlen = px_md_result_size(md);
104
105 res = (text *) palloc(hlen + VARHDRSZ);
106 SET_VARSIZE(res, hlen + VARHDRSZ);
107
110
112 px_md_finish(md, (uint8 *) VARDATA(res));
113 px_md_free(md);
114
117
119}
120
121/* SQL function: hmac(data:bytea, key:bytea, type:text) returns bytea */
123
124Datum
126{
127 bytea *arg;
128 bytea *key;
129 text *name;
130 unsigned len,
131 hlen,
132 klen;
133 PX_HMAC *h;
134 bytea *res;
135
137
138 /* will give error if fails */
139 h = find_provider(name, (PFN) px_find_hmac, "HMAC", 0);
140
141 hlen = px_hmac_result_size(h);
142
143 res = (text *) palloc(hlen + VARHDRSZ);
144 SET_VARSIZE(res, hlen + VARHDRSZ);
145
149 klen = VARSIZE_ANY_EXHDR(key);
150
151 px_hmac_init(h, (uint8 *) VARDATA_ANY(key), klen);
153 px_hmac_finish(h, (uint8 *) VARDATA(res));
154 px_hmac_free(h);
155
159
161}
162
163
164/* SQL function: pg_gen_salt(text) returns text */
166
167Datum
169{
170 text *arg0 = PG_GETARG_TEXT_PP(0);
171 int len;
172 char buf[PX_MAX_SALT_LEN + 1];
173
174 text_to_cstring_buffer(arg0, buf, sizeof(buf));
175 len = px_gen_salt(buf, buf, 0);
176 if (len < 0)
178 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
179 errmsg("gen_salt: %s", px_strerror(len))));
180
181 PG_FREE_IF_COPY(arg0, 0);
182
184}
185
186/* SQL function: pg_gen_salt(text, int4) returns text */
188
189Datum
191{
192 text *arg0 = PG_GETARG_TEXT_PP(0);
193 int rounds = PG_GETARG_INT32(1);
194 int len;
195 char buf[PX_MAX_SALT_LEN + 1];
196
197 text_to_cstring_buffer(arg0, buf, sizeof(buf));
198 len = px_gen_salt(buf, buf, rounds);
199 if (len < 0)
201 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
202 errmsg("gen_salt: %s", px_strerror(len))));
203
204 PG_FREE_IF_COPY(arg0, 0);
205
207}
208
209/* SQL function: pg_crypt(psw:text, salt:text) returns text */
211
212Datum
214{
215 text *arg0 = PG_GETARG_TEXT_PP(0);
216 text *arg1 = PG_GETARG_TEXT_PP(1);
217 char *buf0,
218 *buf1,
219 *cres,
220 *resbuf;
221 text *res;
222
223 buf0 = text_to_cstring(arg0);
224 buf1 = text_to_cstring(arg1);
225
226 resbuf = palloc0(PX_MAX_CRYPT);
227
228 cres = px_crypt(buf0, buf1, resbuf, PX_MAX_CRYPT);
229
230 pfree(buf0);
231 pfree(buf1);
232
233 if (cres == NULL)
235 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
236 errmsg("crypt(3) returned NULL")));
237
238 res = cstring_to_text(cres);
239
240 pfree(resbuf);
241
242 PG_FREE_IF_COPY(arg0, 0);
243 PG_FREE_IF_COPY(arg1, 1);
244
245 PG_RETURN_TEXT_P(res);
246}
247
248/* SQL function: pg_encrypt(bytea, bytea, text) returns bytea */
250
251Datum
253{
254 int err;
255 bytea *data,
256 *key,
257 *res;
258 text *type;
259 PX_Combo *c;
260 unsigned dlen,
261 klen,
262 rlen;
263
265 c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
266
269 dlen = VARSIZE_ANY_EXHDR(data);
270 klen = VARSIZE_ANY_EXHDR(key);
271
272 rlen = px_combo_encrypt_len(c, dlen);
273 res = palloc(VARHDRSZ + rlen);
274
275 err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen, NULL, 0);
276 if (!err)
278 (uint8 *) VARDATA(res), &rlen);
280
284
285 if (err)
286 {
287 pfree(res);
289 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
290 errmsg("encrypt error: %s", px_strerror(err))));
291 }
292
293 SET_VARSIZE(res, VARHDRSZ + rlen);
295}
296
297/* SQL function: pg_decrypt(bytea, bytea, text) returns bytea */
299
300Datum
302{
303 int err;
304 bytea *data,
305 *key,
306 *res;
307 text *type;
308 PX_Combo *c;
309 unsigned dlen,
310 klen,
311 rlen;
312
314 c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
315
318 dlen = VARSIZE_ANY_EXHDR(data);
319 klen = VARSIZE_ANY_EXHDR(key);
320
321 rlen = px_combo_decrypt_len(c, dlen);
322 res = palloc(VARHDRSZ + rlen);
323
324 err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen, NULL, 0);
325 if (!err)
327 (uint8 *) VARDATA(res), &rlen);
328
330
331 if (err)
333 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
334 errmsg("decrypt error: %s", px_strerror(err))));
335
336 SET_VARSIZE(res, VARHDRSZ + rlen);
337
341
343}
344
345/* SQL function: pg_encrypt_iv(bytea, bytea, bytea, text) returns bytea */
347
348Datum
350{
351 int err;
352 bytea *data,
353 *key,
354 *iv,
355 *res;
356 text *type;
357 PX_Combo *c;
358 unsigned dlen,
359 klen,
360 ivlen,
361 rlen;
362
364 c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
365
368 iv = PG_GETARG_BYTEA_PP(2);
369 dlen = VARSIZE_ANY_EXHDR(data);
370 klen = VARSIZE_ANY_EXHDR(key);
371 ivlen = VARSIZE_ANY_EXHDR(iv);
372
373 rlen = px_combo_encrypt_len(c, dlen);
374 res = palloc(VARHDRSZ + rlen);
375
376 err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen,
377 (uint8 *) VARDATA_ANY(iv), ivlen);
378 if (!err)
380 (uint8 *) VARDATA(res), &rlen);
381
383
384 if (err)
386 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
387 errmsg("encrypt_iv error: %s", px_strerror(err))));
388
389 SET_VARSIZE(res, VARHDRSZ + rlen);
390
393 PG_FREE_IF_COPY(iv, 2);
395
397}
398
399/* SQL function: pg_decrypt_iv(bytea, bytea, bytea, text) returns bytea */
401
402Datum
404{
405 int err;
406 bytea *data,
407 *key,
408 *iv,
409 *res;
410 text *type;
411 PX_Combo *c;
412 unsigned dlen,
413 klen,
414 rlen,
415 ivlen;
416
418 c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
419
422 iv = PG_GETARG_BYTEA_PP(2);
423 dlen = VARSIZE_ANY_EXHDR(data);
424 klen = VARSIZE_ANY_EXHDR(key);
425 ivlen = VARSIZE_ANY_EXHDR(iv);
426
427 rlen = px_combo_decrypt_len(c, dlen);
428 res = palloc(VARHDRSZ + rlen);
429
430 err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen,
431 (uint8 *) VARDATA_ANY(iv), ivlen);
432 if (!err)
434 (uint8 *) VARDATA(res), &rlen);
435
437
438 if (err)
440 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
441 errmsg("decrypt_iv error: %s", px_strerror(err))));
442
443 SET_VARSIZE(res, VARHDRSZ + rlen);
444
447 PG_FREE_IF_COPY(iv, 2);
449
451}
452
453/* SQL function: pg_random_bytes(int4) returns bytea */
455
456Datum
458{
459 int len = PG_GETARG_INT32(0);
460 bytea *res;
461
462 if (len < 1 || len > 1024)
464 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
465 errmsg("Length not in range")));
466
467 res = palloc(VARHDRSZ + len);
468 SET_VARSIZE(res, VARHDRSZ + len);
469
470 /* generate result */
471 if (!pg_strong_random(VARDATA(res), len))
473
475}
476
477/* SQL function: gen_random_uuid() returns uuid */
479
480Datum
482{
483 /* redirect to built-in function */
484 return gen_random_uuid(fcinfo);
485}
486
488
489Datum
491{
493}
494
495static void *
497 PFN provider_lookup,
498 const char *desc, int silent)
499{
500 void *res;
501 char *buf;
502 int err;
503
506 false);
507
508 err = provider_lookup(buf, &res);
509
510 if (err && !silent)
512 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
513 errmsg("Cannot use \"%s\": %s", buf, px_strerror(err))));
514
515 pfree(buf);
516
517 return err ? NULL : res;
518}
uint8_t uint8
Definition: c.h:500
#define VARHDRSZ
Definition: c.h:663
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
void DefineCustomEnumVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, const struct config_enum_entry *options, GucContext context, int flags, GucEnumCheckHook check_hook, GucEnumAssignHook assign_hook, GucShowHook show_hook)
Definition: guc.c:5244
void MarkGUCPrefixReserved(const char *className)
Definition: guc.c:5280
@ PGC_SUSET
Definition: guc.h:78
void pfree(void *pointer)
Definition: mcxt.c:2150
void * palloc0(Size size)
Definition: mcxt.c:1973
void * palloc(Size size)
Definition: mcxt.c:1943
int px_find_digest(const char *name, PX_MD **res)
Definition: openssl.c:161
bool CheckFIPSMode(void)
Definition: openssl.c:844
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:349
static const struct config_enum_entry builtin_crypto_options[]
Definition: pgcrypto.c:51
Datum pg_encrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:252
void _PG_init(void)
Definition: pgcrypto.c:68
static void * find_provider(text *name, PFN provider_lookup, const char *desc, int silent)
Definition: pgcrypto.c:496
Datum pg_check_fipsmode(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:490
Datum pg_gen_salt_rounds(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:190
Datum pg_decrypt_iv(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:403
PG_MODULE_MAGIC_EXT(.name="pgcrypto",.version=PG_VERSION)
Datum pg_random_uuid(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:481
Datum pg_hmac(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:125
Datum pg_crypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:213
int(* PFN)(const char *name, void **res)
Definition: pgcrypto.c:58
Datum pg_random_bytes(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:457
PG_FUNCTION_INFO_V1(pg_digest)
Datum pg_gen_salt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:168
int builtin_crypto_enabled
Definition: pgcrypto.c:62
Datum pg_digest(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:89
Datum pg_decrypt(PG_FUNCTION_ARGS)
Definition: pgcrypto.c:301
bool pg_strong_random(void *buf, size_t len)
uintptr_t Datum
Definition: postgres.h:69
char * c
int px_gen_salt(const char *salt_type, char *buf, int rounds)
Definition: px-crypt.c:156
char * px_crypt(const char *psw, const char *salt, char *buf, unsigned len)
Definition: px-crypt.c:102
#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:206
#define px_combo_init(c, key, klen, iv, ivlen)
Definition: px.h:231
#define px_hmac_result_size(hmac)
Definition: px.h:209
#define px_hmac_finish(hmac, buf)
Definition: px.h:214
@ BC_ON
Definition: px.h:94
@ BC_OFF
Definition: px.h:95
@ BC_FIPS
Definition: px.h:96
#define px_combo_encrypt_len(c, dlen)
Definition: px.h:229
#define px_md_free(md)
Definition: px.h:207
#define px_hmac_update(hmac, data, dlen)
Definition: px.h:213
#define px_hmac_init(hmac, key, klen)
Definition: px.h:212
#define px_combo_encrypt(c, data, dlen, res, rlen)
Definition: px.h:233
#define px_hmac_free(hmac)
Definition: px.h:215
#define px_combo_decrypt_len(c, dlen)
Definition: px.h:230
#define px_combo_free(c)
Definition: px.h:237
#define px_combo_decrypt(c, data, dlen, res, rlen)
Definition: px.h:235
#define PXE_NO_RANDOM
Definition: px.h:63
#define px_md_update(md, data, dlen)
Definition: px.h:205
#define px_md_result_size(md)
Definition: px.h:202
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:37
Definition: guc.h:174
Definition: px.h:164
Definition: px.h:108
Definition: px.h:130
Definition: c.h:658
Datum gen_random_uuid(PG_FUNCTION_ARGS)
Definition: uuid.c:528
#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
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:204
text * cstring_to_text(const char *s)
Definition: varlena.c:192
void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len)
Definition: varlena.c:256
char * text_to_cstring(const text *t)
Definition: varlena.c:225
const char * type
const char * name