1 /*
2  * pgp-pgsql.c
3  *		PostgreSQL wrappers for pgp.
4  *
5  * Copyright (c) 2005 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/pgp-pgsql.c
30  */
31 
32 #include "postgres.h"
33 
34 #include "lib/stringinfo.h"
35 #include "catalog/pg_type.h"
36 #include "mb/pg_wchar.h"
37 #include "utils/builtins.h"
38 #include "utils/array.h"
39 #include "funcapi.h"
40 
41 #include "mbuf.h"
42 #include "px.h"
43 #include "pgp.h"
44 
45 /*
46  * public functions
47  */
48 PG_FUNCTION_INFO_V1(pgp_sym_encrypt_bytea);
49 PG_FUNCTION_INFO_V1(pgp_sym_encrypt_text);
50 PG_FUNCTION_INFO_V1(pgp_sym_decrypt_bytea);
51 PG_FUNCTION_INFO_V1(pgp_sym_decrypt_text);
52 
53 PG_FUNCTION_INFO_V1(pgp_pub_encrypt_bytea);
54 PG_FUNCTION_INFO_V1(pgp_pub_encrypt_text);
55 PG_FUNCTION_INFO_V1(pgp_pub_decrypt_bytea);
56 PG_FUNCTION_INFO_V1(pgp_pub_decrypt_text);
57 
58 PG_FUNCTION_INFO_V1(pgp_key_id_w);
59 
60 PG_FUNCTION_INFO_V1(pg_armor);
61 PG_FUNCTION_INFO_V1(pg_dearmor);
62 PG_FUNCTION_INFO_V1(pgp_armor_headers);
63 
64 /*
65  * Mix a block of data into RNG.
66  */
67 static void
add_block_entropy(PX_MD * md,text * data)68 add_block_entropy(PX_MD *md, text *data)
69 {
70 	uint8		sha1[20];
71 
72 	px_md_reset(md);
73 	px_md_update(md, (uint8 *) VARDATA(data), VARSIZE(data) - VARHDRSZ);
74 	px_md_finish(md, sha1);
75 
76 	px_add_entropy(sha1, 20);
77 
78 	px_memset(sha1, 0, 20);
79 }
80 
81 /*
82  * Mix user data into RNG.  It is for user own interests to have
83  * RNG state shuffled.
84  */
85 static void
add_entropy(text * data1,text * data2,text * data3)86 add_entropy(text *data1, text *data2, text *data3)
87 {
88 	PX_MD	   *md;
89 	uint8		rnd[3];
90 
91 	if (!data1 && !data2 && !data3)
92 		return;
93 
94 	if (px_get_random_bytes(rnd, 3) < 0)
95 		return;
96 
97 	if (px_find_digest("sha1", &md) < 0)
98 		return;
99 
100 	/*
101 	 * Try to make the feeding unpredictable.
102 	 *
103 	 * Prefer data over keys, as it's rather likely that key is same in
104 	 * several calls.
105 	 */
106 
107 	/* chance: 7/8 */
108 	if (data1 && rnd[0] >= 32)
109 		add_block_entropy(md, data1);
110 
111 	/* chance: 5/8 */
112 	if (data2 && rnd[1] >= 160)
113 		add_block_entropy(md, data2);
114 
115 	/* chance: 5/8 */
116 	if (data3 && rnd[2] >= 160)
117 		add_block_entropy(md, data3);
118 
119 	px_md_free(md);
120 	px_memset(rnd, 0, sizeof(rnd));
121 }
122 
123 /*
124  * returns src in case of no conversion or error
125  */
126 static text *
convert_charset(text * src,int cset_from,int cset_to)127 convert_charset(text *src, int cset_from, int cset_to)
128 {
129 	int			src_len = VARSIZE(src) - VARHDRSZ;
130 	unsigned char *dst;
131 	unsigned char *csrc = (unsigned char *) VARDATA(src);
132 	text	   *res;
133 
134 	dst = pg_do_encoding_conversion(csrc, src_len, cset_from, cset_to);
135 	if (dst == csrc)
136 		return src;
137 
138 	res = cstring_to_text((char *) dst);
139 	pfree(dst);
140 	return res;
141 }
142 
143 static text *
convert_from_utf8(text * src)144 convert_from_utf8(text *src)
145 {
146 	return convert_charset(src, PG_UTF8, GetDatabaseEncoding());
147 }
148 
149 static text *
convert_to_utf8(text * src)150 convert_to_utf8(text *src)
151 {
152 	return convert_charset(src, GetDatabaseEncoding(), PG_UTF8);
153 }
154 
155 static bool
string_is_ascii(const char * str)156 string_is_ascii(const char *str)
157 {
158 	const char *p;
159 
160 	for (p = str; *p; p++)
161 	{
162 		if (IS_HIGHBIT_SET(*p))
163 			return false;
164 	}
165 	return true;
166 }
167 
168 static void
clear_and_pfree(text * p)169 clear_and_pfree(text *p)
170 {
171 	px_memset(p, 0, VARSIZE(p));
172 	pfree(p);
173 }
174 
175 /*
176  * expect-* arguments storage
177  */
178 struct debug_expect
179 {
180 	int			debug;
181 	int			expect;
182 	int			cipher_algo;
183 	int			s2k_mode;
184 	int			s2k_count;
185 	int			s2k_cipher_algo;
186 	int			s2k_digest_algo;
187 	int			compress_algo;
188 	int			use_sess_key;
189 	int			disable_mdc;
190 	int			unicode_mode;
191 };
192 
193 static void
fill_expect(struct debug_expect * ex,int text_mode)194 fill_expect(struct debug_expect * ex, int text_mode)
195 {
196 	ex->debug = 0;
197 	ex->expect = 0;
198 	ex->cipher_algo = -1;
199 	ex->s2k_mode = -1;
200 	ex->s2k_count = -1;
201 	ex->s2k_cipher_algo = -1;
202 	ex->s2k_digest_algo = -1;
203 	ex->compress_algo = -1;
204 	ex->use_sess_key = -1;
205 	ex->disable_mdc = -1;
206 	ex->unicode_mode = -1;
207 }
208 
209 #define EX_MSG(arg) \
210 	ereport(NOTICE, (errmsg( \
211 		"pgp_decrypt: unexpected %s: expected %d got %d", \
212 		CppAsString(arg), ex->arg, ctx->arg)))
213 
214 #define EX_CHECK(arg) do { \
215 		if (ex->arg >= 0 && ex->arg != ctx->arg) EX_MSG(arg); \
216 	} while (0)
217 
218 static void
check_expect(PGP_Context * ctx,struct debug_expect * ex)219 check_expect(PGP_Context *ctx, struct debug_expect * ex)
220 {
221 	EX_CHECK(cipher_algo);
222 	EX_CHECK(s2k_mode);
223 	EX_CHECK(s2k_count);
224 	EX_CHECK(s2k_digest_algo);
225 	EX_CHECK(use_sess_key);
226 	if (ctx->use_sess_key)
227 		EX_CHECK(s2k_cipher_algo);
228 	EX_CHECK(disable_mdc);
229 	EX_CHECK(compress_algo);
230 	EX_CHECK(unicode_mode);
231 }
232 
233 static void
show_debug(const char * msg)234 show_debug(const char *msg)
235 {
236 	ereport(NOTICE, (errmsg("dbg: %s", msg)));
237 }
238 
239 static int
set_arg(PGP_Context * ctx,char * key,char * val,struct debug_expect * ex)240 set_arg(PGP_Context *ctx, char *key, char *val,
241 		struct debug_expect * ex)
242 {
243 	int			res = 0;
244 
245 	if (strcmp(key, "cipher-algo") == 0)
246 		res = pgp_set_cipher_algo(ctx, val);
247 	else if (strcmp(key, "disable-mdc") == 0)
248 		res = pgp_disable_mdc(ctx, atoi(val));
249 	else if (strcmp(key, "sess-key") == 0)
250 		res = pgp_set_sess_key(ctx, atoi(val));
251 	else if (strcmp(key, "s2k-mode") == 0)
252 		res = pgp_set_s2k_mode(ctx, atoi(val));
253 	else if (strcmp(key, "s2k-count") == 0)
254 		res = pgp_set_s2k_count(ctx, atoi(val));
255 	else if (strcmp(key, "s2k-digest-algo") == 0)
256 		res = pgp_set_s2k_digest_algo(ctx, val);
257 	else if (strcmp(key, "s2k-cipher-algo") == 0)
258 		res = pgp_set_s2k_cipher_algo(ctx, val);
259 	else if (strcmp(key, "compress-algo") == 0)
260 		res = pgp_set_compress_algo(ctx, atoi(val));
261 	else if (strcmp(key, "compress-level") == 0)
262 		res = pgp_set_compress_level(ctx, atoi(val));
263 	else if (strcmp(key, "convert-crlf") == 0)
264 		res = pgp_set_convert_crlf(ctx, atoi(val));
265 	else if (strcmp(key, "unicode-mode") == 0)
266 		res = pgp_set_unicode_mode(ctx, atoi(val));
267 
268 	/*
269 	 * The remaining options are for debugging/testing and are therefore not
270 	 * documented in the user-facing docs.
271 	 */
272 	else if (ex != NULL && strcmp(key, "debug") == 0)
273 		ex->debug = atoi(val);
274 	else if (ex != NULL && strcmp(key, "expect-cipher-algo") == 0)
275 	{
276 		ex->expect = 1;
277 		ex->cipher_algo = pgp_get_cipher_code(val);
278 	}
279 	else if (ex != NULL && strcmp(key, "expect-disable-mdc") == 0)
280 	{
281 		ex->expect = 1;
282 		ex->disable_mdc = atoi(val);
283 	}
284 	else if (ex != NULL && strcmp(key, "expect-sess-key") == 0)
285 	{
286 		ex->expect = 1;
287 		ex->use_sess_key = atoi(val);
288 	}
289 	else if (ex != NULL && strcmp(key, "expect-s2k-mode") == 0)
290 	{
291 		ex->expect = 1;
292 		ex->s2k_mode = atoi(val);
293 	}
294 	else if (ex != NULL && strcmp(key, "expect-s2k-count") == 0)
295 	{
296 		ex->expect = 1;
297 		ex->s2k_count = atoi(val);
298 	}
299 	else if (ex != NULL && strcmp(key, "expect-s2k-digest-algo") == 0)
300 	{
301 		ex->expect = 1;
302 		ex->s2k_digest_algo = pgp_get_digest_code(val);
303 	}
304 	else if (ex != NULL && strcmp(key, "expect-s2k-cipher-algo") == 0)
305 	{
306 		ex->expect = 1;
307 		ex->s2k_cipher_algo = pgp_get_cipher_code(val);
308 	}
309 	else if (ex != NULL && strcmp(key, "expect-compress-algo") == 0)
310 	{
311 		ex->expect = 1;
312 		ex->compress_algo = atoi(val);
313 	}
314 	else if (ex != NULL && strcmp(key, "expect-unicode-mode") == 0)
315 	{
316 		ex->expect = 1;
317 		ex->unicode_mode = atoi(val);
318 	}
319 	else
320 		res = PXE_ARGUMENT_ERROR;
321 
322 	return res;
323 }
324 
325 /*
326  * Find next word.  Handle ',' and '=' as words.  Skip whitespace.
327  * Put word info into res_p, res_len.
328  * Returns ptr to next word.
329  */
330 static char *
getword(char * p,char ** res_p,int * res_len)331 getword(char *p, char **res_p, int *res_len)
332 {
333 	/* whitespace at start */
334 	while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
335 		p++;
336 
337 	/* word data */
338 	*res_p = p;
339 	if (*p == '=' || *p == ',')
340 		p++;
341 	else
342 		while (*p && !(*p == ' ' || *p == '\t' || *p == '\n'
343 					   || *p == '=' || *p == ','))
344 			p++;
345 
346 	/* word end */
347 	*res_len = p - *res_p;
348 
349 	/* whitespace at end */
350 	while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
351 		p++;
352 
353 	return p;
354 }
355 
356 /*
357  * Convert to lowercase asciiz string.
358  */
359 static char *
downcase_convert(const uint8 * s,int len)360 downcase_convert(const uint8 *s, int len)
361 {
362 	int			c,
363 				i;
364 	char	   *res = palloc(len + 1);
365 
366 	for (i = 0; i < len; i++)
367 	{
368 		c = s[i];
369 		if (c >= 'A' && c <= 'Z')
370 			c += 'a' - 'A';
371 		res[i] = c;
372 	}
373 	res[len] = 0;
374 	return res;
375 }
376 
377 static int
parse_args(PGP_Context * ctx,uint8 * args,int arg_len,struct debug_expect * ex)378 parse_args(PGP_Context *ctx, uint8 *args, int arg_len,
379 		   struct debug_expect * ex)
380 {
381 	char	   *str = downcase_convert(args, arg_len);
382 	char	   *key,
383 			   *val;
384 	int			key_len,
385 				val_len;
386 	int			res = 0;
387 	char	   *p = str;
388 
389 	while (*p)
390 	{
391 		res = PXE_ARGUMENT_ERROR;
392 		p = getword(p, &key, &key_len);
393 		if (*p++ != '=')
394 			break;
395 		p = getword(p, &val, &val_len);
396 		if (*p == '\0')
397 			;
398 		else if (*p++ != ',')
399 			break;
400 
401 		if (*key == 0 || *val == 0 || val_len == 0)
402 			break;
403 
404 		key[key_len] = 0;
405 		val[val_len] = 0;
406 
407 		res = set_arg(ctx, key, val, ex);
408 		if (res < 0)
409 			break;
410 	}
411 	pfree(str);
412 	return res;
413 }
414 
415 static MBuf *
create_mbuf_from_vardata(text * data)416 create_mbuf_from_vardata(text *data)
417 {
418 	return mbuf_create_from_data((uint8 *) VARDATA(data),
419 								 VARSIZE(data) - VARHDRSZ);
420 }
421 
422 static void
init_work(PGP_Context ** ctx_p,int is_text,text * args,struct debug_expect * ex)423 init_work(PGP_Context **ctx_p, int is_text,
424 		  text *args, struct debug_expect * ex)
425 {
426 	int			err = pgp_init(ctx_p);
427 
428 	fill_expect(ex, is_text);
429 
430 	if (err == 0 && args != NULL)
431 		err = parse_args(*ctx_p, (uint8 *) VARDATA(args),
432 						 VARSIZE(args) - VARHDRSZ, ex);
433 
434 	if (err)
435 	{
436 		ereport(ERROR,
437 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
438 				 errmsg("%s", px_strerror(err))));
439 	}
440 
441 	if (ex->debug)
442 		px_set_debug_handler(show_debug);
443 
444 	pgp_set_text_mode(*ctx_p, is_text);
445 }
446 
447 static bytea *
encrypt_internal(int is_pubenc,int is_text,text * data,text * key,text * args)448 encrypt_internal(int is_pubenc, int is_text,
449 				 text *data, text *key, text *args)
450 {
451 	MBuf	   *src,
452 			   *dst;
453 	uint8		tmp[VARHDRSZ];
454 	uint8	   *restmp;
455 	bytea	   *res;
456 	int			res_len;
457 	PGP_Context *ctx;
458 	int			err;
459 	struct debug_expect ex;
460 	text	   *tmp_data = NULL;
461 
462 	/*
463 	 * Add data and key info RNG.
464 	 */
465 	add_entropy(data, key, NULL);
466 
467 	init_work(&ctx, is_text, args, &ex);
468 
469 	if (is_text && pgp_get_unicode_mode(ctx))
470 	{
471 		tmp_data = convert_to_utf8(data);
472 		if (tmp_data == data)
473 			tmp_data = NULL;
474 		else
475 			data = tmp_data;
476 	}
477 
478 	src = create_mbuf_from_vardata(data);
479 	dst = mbuf_create(VARSIZE(data) + 128);
480 
481 	/*
482 	 * reserve room for header
483 	 */
484 	mbuf_append(dst, tmp, VARHDRSZ);
485 
486 	/*
487 	 * set key
488 	 */
489 	if (is_pubenc)
490 	{
491 		MBuf	   *kbuf = create_mbuf_from_vardata(key);
492 
493 		err = pgp_set_pubkey(ctx, kbuf,
494 							 NULL, 0, 0);
495 		mbuf_free(kbuf);
496 	}
497 	else
498 		err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key),
499 							 VARSIZE(key) - VARHDRSZ);
500 
501 	/*
502 	 * encrypt
503 	 */
504 	if (err >= 0)
505 		err = pgp_encrypt(ctx, src, dst);
506 
507 	/*
508 	 * check for error
509 	 */
510 	if (err)
511 	{
512 		if (ex.debug)
513 			px_set_debug_handler(NULL);
514 		if (tmp_data)
515 			clear_and_pfree(tmp_data);
516 		pgp_free(ctx);
517 		mbuf_free(src);
518 		mbuf_free(dst);
519 		ereport(ERROR,
520 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
521 				 errmsg("%s", px_strerror(err))));
522 	}
523 
524 	/* res_len includes VARHDRSZ */
525 	res_len = mbuf_steal_data(dst, &restmp);
526 	res = (bytea *) restmp;
527 	SET_VARSIZE(res, res_len);
528 
529 	if (tmp_data)
530 		clear_and_pfree(tmp_data);
531 	pgp_free(ctx);
532 	mbuf_free(src);
533 	mbuf_free(dst);
534 
535 	px_set_debug_handler(NULL);
536 
537 	return res;
538 }
539 
540 static bytea *
decrypt_internal(int is_pubenc,int need_text,text * data,text * key,text * keypsw,text * args)541 decrypt_internal(int is_pubenc, int need_text, text *data,
542 				 text *key, text *keypsw, text *args)
543 {
544 	int			err;
545 	MBuf	   *src = NULL,
546 			   *dst = NULL;
547 	uint8		tmp[VARHDRSZ];
548 	uint8	   *restmp;
549 	bytea	   *res;
550 	int			res_len;
551 	PGP_Context *ctx = NULL;
552 	struct debug_expect ex;
553 	int			got_unicode = 0;
554 
555 
556 	init_work(&ctx, need_text, args, &ex);
557 
558 	src = mbuf_create_from_data((uint8 *) VARDATA(data),
559 								VARSIZE(data) - VARHDRSZ);
560 	dst = mbuf_create(VARSIZE(data) + 2048);
561 
562 	/*
563 	 * reserve room for header
564 	 */
565 	mbuf_append(dst, tmp, VARHDRSZ);
566 
567 	/*
568 	 * set key
569 	 */
570 	if (is_pubenc)
571 	{
572 		uint8	   *psw = NULL;
573 		int			psw_len = 0;
574 		MBuf	   *kbuf;
575 
576 		if (keypsw)
577 		{
578 			psw = (uint8 *) VARDATA(keypsw);
579 			psw_len = VARSIZE(keypsw) - VARHDRSZ;
580 		}
581 		kbuf = create_mbuf_from_vardata(key);
582 		err = pgp_set_pubkey(ctx, kbuf, psw, psw_len, 1);
583 		mbuf_free(kbuf);
584 	}
585 	else
586 		err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key),
587 							 VARSIZE(key) - VARHDRSZ);
588 
589 	/* decrypt */
590 	if (err >= 0)
591 	{
592 		err = pgp_decrypt(ctx, src, dst);
593 
594 		if (ex.expect)
595 			check_expect(ctx, &ex);
596 
597 		/* remember the setting */
598 		got_unicode = pgp_get_unicode_mode(ctx);
599 	}
600 
601 	mbuf_free(src);
602 	pgp_free(ctx);
603 
604 	if (err)
605 	{
606 		px_set_debug_handler(NULL);
607 		mbuf_free(dst);
608 		ereport(ERROR,
609 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
610 				 errmsg("%s", px_strerror(err))));
611 	}
612 
613 	res_len = mbuf_steal_data(dst, &restmp);
614 	mbuf_free(dst);
615 
616 	/* res_len includes VARHDRSZ */
617 	res = (bytea *) restmp;
618 	SET_VARSIZE(res, res_len);
619 
620 	if (need_text && got_unicode)
621 	{
622 		text	   *utf = convert_from_utf8(res);
623 
624 		if (utf != res)
625 		{
626 			clear_and_pfree(res);
627 			res = utf;
628 		}
629 	}
630 	px_set_debug_handler(NULL);
631 
632 	/*
633 	 * add successful decryptions also into RNG
634 	 */
635 	add_entropy(res, key, keypsw);
636 
637 	return res;
638 }
639 
640 /*
641  * Wrappers for symmetric-key functions
642  */
643 Datum
pgp_sym_encrypt_bytea(PG_FUNCTION_ARGS)644 pgp_sym_encrypt_bytea(PG_FUNCTION_ARGS)
645 {
646 	bytea	   *data,
647 			   *key;
648 	text	   *arg = NULL;
649 	text	   *res;
650 
651 	data = PG_GETARG_BYTEA_P(0);
652 	key = PG_GETARG_BYTEA_P(1);
653 	if (PG_NARGS() > 2)
654 		arg = PG_GETARG_BYTEA_P(2);
655 
656 	res = encrypt_internal(0, 0, data, key, arg);
657 
658 	PG_FREE_IF_COPY(data, 0);
659 	PG_FREE_IF_COPY(key, 1);
660 	if (PG_NARGS() > 2)
661 		PG_FREE_IF_COPY(arg, 2);
662 	PG_RETURN_TEXT_P(res);
663 }
664 
665 Datum
pgp_sym_encrypt_text(PG_FUNCTION_ARGS)666 pgp_sym_encrypt_text(PG_FUNCTION_ARGS)
667 {
668 	bytea	   *data,
669 			   *key;
670 	text	   *arg = NULL;
671 	text	   *res;
672 
673 	data = PG_GETARG_BYTEA_P(0);
674 	key = PG_GETARG_BYTEA_P(1);
675 	if (PG_NARGS() > 2)
676 		arg = PG_GETARG_BYTEA_P(2);
677 
678 	res = encrypt_internal(0, 1, data, key, arg);
679 
680 	PG_FREE_IF_COPY(data, 0);
681 	PG_FREE_IF_COPY(key, 1);
682 	if (PG_NARGS() > 2)
683 		PG_FREE_IF_COPY(arg, 2);
684 	PG_RETURN_TEXT_P(res);
685 }
686 
687 
688 Datum
pgp_sym_decrypt_bytea(PG_FUNCTION_ARGS)689 pgp_sym_decrypt_bytea(PG_FUNCTION_ARGS)
690 {
691 	bytea	   *data,
692 			   *key;
693 	text	   *arg = NULL;
694 	text	   *res;
695 
696 	data = PG_GETARG_BYTEA_P(0);
697 	key = PG_GETARG_BYTEA_P(1);
698 	if (PG_NARGS() > 2)
699 		arg = PG_GETARG_BYTEA_P(2);
700 
701 	res = decrypt_internal(0, 0, data, key, NULL, arg);
702 
703 	PG_FREE_IF_COPY(data, 0);
704 	PG_FREE_IF_COPY(key, 1);
705 	if (PG_NARGS() > 2)
706 		PG_FREE_IF_COPY(arg, 2);
707 	PG_RETURN_TEXT_P(res);
708 }
709 
710 Datum
pgp_sym_decrypt_text(PG_FUNCTION_ARGS)711 pgp_sym_decrypt_text(PG_FUNCTION_ARGS)
712 {
713 	bytea	   *data,
714 			   *key;
715 	text	   *arg = NULL;
716 	text	   *res;
717 
718 	data = PG_GETARG_BYTEA_P(0);
719 	key = PG_GETARG_BYTEA_P(1);
720 	if (PG_NARGS() > 2)
721 		arg = PG_GETARG_BYTEA_P(2);
722 
723 	res = decrypt_internal(0, 1, data, key, NULL, arg);
724 
725 	PG_FREE_IF_COPY(data, 0);
726 	PG_FREE_IF_COPY(key, 1);
727 	if (PG_NARGS() > 2)
728 		PG_FREE_IF_COPY(arg, 2);
729 	PG_RETURN_TEXT_P(res);
730 }
731 
732 /*
733  * Wrappers for public-key functions
734  */
735 
736 Datum
pgp_pub_encrypt_bytea(PG_FUNCTION_ARGS)737 pgp_pub_encrypt_bytea(PG_FUNCTION_ARGS)
738 {
739 	bytea	   *data,
740 			   *key;
741 	text	   *arg = NULL;
742 	text	   *res;
743 
744 	data = PG_GETARG_BYTEA_P(0);
745 	key = PG_GETARG_BYTEA_P(1);
746 	if (PG_NARGS() > 2)
747 		arg = PG_GETARG_BYTEA_P(2);
748 
749 	res = encrypt_internal(1, 0, data, key, arg);
750 
751 	PG_FREE_IF_COPY(data, 0);
752 	PG_FREE_IF_COPY(key, 1);
753 	if (PG_NARGS() > 2)
754 		PG_FREE_IF_COPY(arg, 2);
755 	PG_RETURN_TEXT_P(res);
756 }
757 
758 Datum
pgp_pub_encrypt_text(PG_FUNCTION_ARGS)759 pgp_pub_encrypt_text(PG_FUNCTION_ARGS)
760 {
761 	bytea	   *data,
762 			   *key;
763 	text	   *arg = NULL;
764 	text	   *res;
765 
766 	data = PG_GETARG_BYTEA_P(0);
767 	key = PG_GETARG_BYTEA_P(1);
768 	if (PG_NARGS() > 2)
769 		arg = PG_GETARG_BYTEA_P(2);
770 
771 	res = encrypt_internal(1, 1, data, key, arg);
772 
773 	PG_FREE_IF_COPY(data, 0);
774 	PG_FREE_IF_COPY(key, 1);
775 	if (PG_NARGS() > 2)
776 		PG_FREE_IF_COPY(arg, 2);
777 	PG_RETURN_TEXT_P(res);
778 }
779 
780 
781 Datum
pgp_pub_decrypt_bytea(PG_FUNCTION_ARGS)782 pgp_pub_decrypt_bytea(PG_FUNCTION_ARGS)
783 {
784 	bytea	   *data,
785 			   *key;
786 	text	   *psw = NULL,
787 			   *arg = NULL;
788 	text	   *res;
789 
790 	data = PG_GETARG_BYTEA_P(0);
791 	key = PG_GETARG_BYTEA_P(1);
792 	if (PG_NARGS() > 2)
793 		psw = PG_GETARG_BYTEA_P(2);
794 	if (PG_NARGS() > 3)
795 		arg = PG_GETARG_BYTEA_P(3);
796 
797 	res = decrypt_internal(1, 0, data, key, psw, arg);
798 
799 	PG_FREE_IF_COPY(data, 0);
800 	PG_FREE_IF_COPY(key, 1);
801 	if (PG_NARGS() > 2)
802 		PG_FREE_IF_COPY(psw, 2);
803 	if (PG_NARGS() > 3)
804 		PG_FREE_IF_COPY(arg, 3);
805 	PG_RETURN_TEXT_P(res);
806 }
807 
808 Datum
pgp_pub_decrypt_text(PG_FUNCTION_ARGS)809 pgp_pub_decrypt_text(PG_FUNCTION_ARGS)
810 {
811 	bytea	   *data,
812 			   *key;
813 	text	   *psw = NULL,
814 			   *arg = NULL;
815 	text	   *res;
816 
817 	data = PG_GETARG_BYTEA_P(0);
818 	key = PG_GETARG_BYTEA_P(1);
819 	if (PG_NARGS() > 2)
820 		psw = PG_GETARG_BYTEA_P(2);
821 	if (PG_NARGS() > 3)
822 		arg = PG_GETARG_BYTEA_P(3);
823 
824 	res = decrypt_internal(1, 1, data, key, psw, arg);
825 
826 	PG_FREE_IF_COPY(data, 0);
827 	PG_FREE_IF_COPY(key, 1);
828 	if (PG_NARGS() > 2)
829 		PG_FREE_IF_COPY(psw, 2);
830 	if (PG_NARGS() > 3)
831 		PG_FREE_IF_COPY(arg, 3);
832 	PG_RETURN_TEXT_P(res);
833 }
834 
835 
836 /*
837  * Wrappers for PGP ascii armor
838  */
839 
840 /*
841  * Helper function for pgp_armor. Converts arrays of keys and values into
842  * plain C arrays, and checks that they don't contain invalid characters.
843  */
844 static int
parse_key_value_arrays(ArrayType * key_array,ArrayType * val_array,char *** p_keys,char *** p_values)845 parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
846 					   char ***p_keys, char ***p_values)
847 {
848 	int			nkdims = ARR_NDIM(key_array);
849 	int			nvdims = ARR_NDIM(val_array);
850 	char	  **keys,
851 			  **values;
852 	Datum	   *key_datums,
853 			   *val_datums;
854 	bool	   *key_nulls,
855 			   *val_nulls;
856 	int			key_count,
857 				val_count;
858 	int			i;
859 
860 	if (nkdims > 1 || nkdims != nvdims)
861 		ereport(ERROR,
862 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
863 				 errmsg("wrong number of array subscripts")));
864 	if (nkdims == 0)
865 		return 0;
866 
867 	deconstruct_array(key_array,
868 					  TEXTOID, -1, false, 'i',
869 					  &key_datums, &key_nulls, &key_count);
870 
871 	deconstruct_array(val_array,
872 					  TEXTOID, -1, false, 'i',
873 					  &val_datums, &val_nulls, &val_count);
874 
875 	if (key_count != val_count)
876 		ereport(ERROR,
877 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
878 				 errmsg("mismatched array dimensions")));
879 
880 	keys = (char **) palloc(sizeof(char *) * key_count);
881 	values = (char **) palloc(sizeof(char *) * val_count);
882 
883 	for (i = 0; i < key_count; i++)
884 	{
885 		char	   *v;
886 
887 		/* Check that the key doesn't contain anything funny */
888 		if (key_nulls[i])
889 			ereport(ERROR,
890 					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
891 					 errmsg("null value not allowed for header key")));
892 
893 		v = TextDatumGetCString(key_datums[i]);
894 
895 		if (!string_is_ascii(v))
896 			ereport(ERROR,
897 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
898 				errmsg("header key must not contain non-ASCII characters")));
899 		if (strstr(v, ": "))
900 			ereport(ERROR,
901 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
902 					 errmsg("header key must not contain \": \"")));
903 		if (strchr(v, '\n'))
904 			ereport(ERROR,
905 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
906 					 errmsg("header key must not contain newlines")));
907 		keys[i] = v;
908 
909 		/* And the same for the value */
910 		if (val_nulls[i])
911 			ereport(ERROR,
912 					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
913 					 errmsg("null value not allowed for header value")));
914 
915 		v = TextDatumGetCString(val_datums[i]);
916 
917 		if (!string_is_ascii(v))
918 			ereport(ERROR,
919 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
920 			  errmsg("header value must not contain non-ASCII characters")));
921 		if (strchr(v, '\n'))
922 			ereport(ERROR,
923 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
924 					 errmsg("header value must not contain newlines")));
925 
926 		values[i] = v;
927 	}
928 
929 	*p_keys = keys;
930 	*p_values = values;
931 	return key_count;
932 }
933 
934 Datum
pg_armor(PG_FUNCTION_ARGS)935 pg_armor(PG_FUNCTION_ARGS)
936 {
937 	bytea	   *data;
938 	text	   *res;
939 	int			data_len;
940 	StringInfoData buf;
941 	int			num_headers;
942 	char	  **keys = NULL,
943 			  **values = NULL;
944 
945 	data = PG_GETARG_BYTEA_P(0);
946 	data_len = VARSIZE(data) - VARHDRSZ;
947 	if (PG_NARGS() == 3)
948 	{
949 		num_headers = parse_key_value_arrays(PG_GETARG_ARRAYTYPE_P(1),
950 											 PG_GETARG_ARRAYTYPE_P(2),
951 											 &keys, &values);
952 	}
953 	else if (PG_NARGS() == 1)
954 		num_headers = 0;
955 	else
956 		elog(ERROR, "unexpected number of arguments %d", PG_NARGS());
957 
958 	initStringInfo(&buf);
959 
960 	pgp_armor_encode((uint8 *) VARDATA(data), data_len, &buf,
961 					 num_headers, keys, values);
962 
963 	res = palloc(VARHDRSZ + buf.len);
964 	SET_VARSIZE(res, VARHDRSZ + buf.len);
965 	memcpy(VARDATA(res), buf.data, buf.len);
966 	pfree(buf.data);
967 
968 	PG_FREE_IF_COPY(data, 0);
969 	PG_RETURN_TEXT_P(res);
970 }
971 
972 Datum
pg_dearmor(PG_FUNCTION_ARGS)973 pg_dearmor(PG_FUNCTION_ARGS)
974 {
975 	text	   *data;
976 	bytea	   *res;
977 	int			data_len;
978 	int			ret;
979 	StringInfoData buf;
980 
981 	data = PG_GETARG_TEXT_P(0);
982 	data_len = VARSIZE(data) - VARHDRSZ;
983 
984 	initStringInfo(&buf);
985 
986 	ret = pgp_armor_decode((uint8 *) VARDATA(data), data_len, &buf);
987 	if (ret < 0)
988 		ereport(ERROR,
989 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
990 				 errmsg("%s", px_strerror(ret))));
991 	res = palloc(VARHDRSZ + buf.len);
992 	SET_VARSIZE(res, VARHDRSZ + buf.len);
993 	memcpy(VARDATA(res), buf.data, buf.len);
994 	pfree(buf.data);
995 
996 	PG_FREE_IF_COPY(data, 0);
997 	PG_RETURN_TEXT_P(res);
998 }
999 
1000 /* cross-call state for pgp_armor_headers */
1001 typedef struct
1002 {
1003 	int			nheaders;
1004 	char	  **keys;
1005 	char	  **values;
1006 } pgp_armor_headers_state;
1007 
1008 Datum
pgp_armor_headers(PG_FUNCTION_ARGS)1009 pgp_armor_headers(PG_FUNCTION_ARGS)
1010 {
1011 	FuncCallContext *funcctx;
1012 	pgp_armor_headers_state *state;
1013 	char	   *utf8key;
1014 	char	   *utf8val;
1015 	HeapTuple	tuple;
1016 	TupleDesc	tupdesc;
1017 	AttInMetadata *attinmeta;
1018 
1019 	if (SRF_IS_FIRSTCALL())
1020 	{
1021 		text	   *data = PG_GETARG_TEXT_PP(0);
1022 		int			res;
1023 		MemoryContext oldcontext;
1024 
1025 		funcctx = SRF_FIRSTCALL_INIT();
1026 
1027 		/* we need the state allocated in the multi call context */
1028 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1029 
1030 		/* Build a tuple descriptor for our result type */
1031 		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1032 			elog(ERROR, "return type must be a row type");
1033 
1034 		attinmeta = TupleDescGetAttInMetadata(tupdesc);
1035 		funcctx->attinmeta = attinmeta;
1036 
1037 		state = (pgp_armor_headers_state *) palloc(sizeof(pgp_armor_headers_state));
1038 
1039 		res = pgp_extract_armor_headers((uint8 *) VARDATA_ANY(data),
1040 										VARSIZE_ANY_EXHDR(data),
1041 										&state->nheaders, &state->keys,
1042 										&state->values);
1043 		if (res < 0)
1044 			ereport(ERROR,
1045 					(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
1046 					 errmsg("%s", px_strerror(res))));
1047 
1048 		MemoryContextSwitchTo(oldcontext);
1049 		funcctx->user_fctx = state;
1050 	}
1051 
1052 	funcctx = SRF_PERCALL_SETUP();
1053 	state = (pgp_armor_headers_state *) funcctx->user_fctx;
1054 
1055 	if (funcctx->call_cntr >= state->nheaders)
1056 		SRF_RETURN_DONE(funcctx);
1057 	else
1058 	{
1059 		char	   *values[2];
1060 
1061 		/* we assume that the keys (and values) are in UTF-8. */
1062 		utf8key = state->keys[funcctx->call_cntr];
1063 		utf8val = state->values[funcctx->call_cntr];
1064 
1065 		values[0] = pg_any_to_server(utf8key, strlen(utf8key), PG_UTF8);
1066 		values[1] = pg_any_to_server(utf8val, strlen(utf8val), PG_UTF8);
1067 
1068 		/* build a tuple */
1069 		tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
1070 		SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
1071 	}
1072 }
1073 
1074 
1075 
1076 /*
1077  * Wrappers for PGP key id
1078  */
1079 
1080 Datum
pgp_key_id_w(PG_FUNCTION_ARGS)1081 pgp_key_id_w(PG_FUNCTION_ARGS)
1082 {
1083 	bytea	   *data;
1084 	text	   *res;
1085 	int			res_len;
1086 	MBuf	   *buf;
1087 
1088 	data = PG_GETARG_BYTEA_P(0);
1089 	buf = create_mbuf_from_vardata(data);
1090 	res = palloc(VARHDRSZ + 17);
1091 
1092 	res_len = pgp_get_keyid(buf, VARDATA(res));
1093 	mbuf_free(buf);
1094 	if (res_len < 0)
1095 		ereport(ERROR,
1096 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
1097 				 errmsg("%s", px_strerror(res_len))));
1098 	SET_VARSIZE(res, VARHDRSZ + res_len);
1099 
1100 	PG_FREE_IF_COPY(data, 0);
1101 	PG_RETURN_TEXT_P(res);
1102 }
1103