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