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